From 44b7e1bf417a7e60652ee40498d711b3281efb0e Mon Sep 17 00:00:00 2001 From: chengyongru Date: Mon, 3 Aug 2026 17:20:17 +0800 Subject: [PATCH] fix(providers): keep serde errors explicit --- nanobot/providers/openai_compat_provider.py | 10 ------- .../test_responses_circuit_breaker.py | 27 +++---------------- 2 files changed, 4 insertions(+), 33 deletions(-) diff --git a/nanobot/providers/openai_compat_provider.py b/nanobot/providers/openai_compat_provider.py index da3c61218..7b6238f22 100644 --- a/nanobot/providers/openai_compat_provider.py +++ b/nanobot/providers/openai_compat_provider.py @@ -1082,16 +1082,6 @@ class OpenAICompatProvider(LLMProvider): "not supported", "unknown parameter", "unrecognized request argument", - # Serde-style body rejection: the endpoint could not parse the - # Responses wire format (e.g. DeepSeek's Responses gateway - # rejecting an input item shape with "Failed to deserialize the - # JSON body ... expected a sequence"). These are compatibility - # failures: fall back to Chat Completions for the same model. - "failed to deserialize", - "invalid type", - "expected a sequence", - "expected a struct", - "unknown field", ) return any(marker in body_text for marker in compatibility_markers) diff --git a/tests/providers/test_responses_circuit_breaker.py b/tests/providers/test_responses_circuit_breaker.py index fa46db73a..ca3e6c40a 100644 --- a/tests/providers/test_responses_circuit_breaker.py +++ b/tests/providers/test_responses_circuit_breaker.py @@ -166,8 +166,9 @@ class _FakeAPIError(Exception): self.response = None -def test_serde_deserialize_error_triggers_fallback(): - # DeepSeek Responses gateway rejecting the wire body (observed Aug 2026). +def test_serde_deserialize_error_does_not_trigger_fallback(): + # Serde errors can also identify malformed user-provided request fields. + # The known DeepSeek wire-shape bug is fixed at serialization time instead. err = _FakeAPIError(400, { "message": ( "Failed to deserialize the JSON body into the target type: " @@ -177,17 +178,7 @@ def test_serde_deserialize_error_triggers_fallback(): "type": "invalid_request_error", "param": None, }) - assert OpenAICompatProvider._should_fallback_from_responses_error(err) is True - - -def test_invalid_type_error_triggers_fallback(): - err = _FakeAPIError(422, "input[0]: invalid type: map, expected a string") - assert OpenAICompatProvider._should_fallback_from_responses_error(err) is True - - -def test_unknown_field_error_triggers_fallback(): - err = _FakeAPIError(400, "unknown field `foo`, expected one of `input`, `instructions`") - assert OpenAICompatProvider._should_fallback_from_responses_error(err) is True + assert OpenAICompatProvider._should_fallback_from_responses_error(err) is False def test_legacy_compatibility_markers_still_trigger_fallback(): @@ -195,16 +186,6 @@ def test_legacy_compatibility_markers_still_trigger_fallback(): assert OpenAICompatProvider._should_fallback_from_responses_error(err) is True -def test_unrelated_400_does_not_trigger_fallback(): - err = _FakeAPIError(400, {"message": "rate limit exceeded", "type": "rate_limit_error"}) - assert OpenAICompatProvider._should_fallback_from_responses_error(err) is False - - -def test_server_error_does_not_trigger_fallback(): - err = _FakeAPIError(500, {"message": "internal server error"}) - assert OpenAICompatProvider._should_fallback_from_responses_error(err) is False - - # ====================================================================== # DeepSeek Responses wire shape (PR #5214 root cause) # ======================================================================