Skip to content

fix: fallback model never triggers on a malformed provider response - #117

Open
fabceolin wants to merge 2 commits into
FSoft-AI4Code:mainfrom
fabceolin:fix/fallback-missing-unexpected-model-behavior
Open

fabceolin wants to merge 2 commits into
FSoft-AI4Code:mainfrom
fabceolin:fix/fallback-missing-unexpected-model-behavior

Conversation

@fabceolin

Copy link
Copy Markdown
Contributor

Problem

FallbackModel's default fallback_on=(ModelAPIError,) does not cover UnexpectedModelBehavior, which pydantic-ai raises for a 200 response whose body doesn't match the expected schema. Seen against OpenRouter on a real run (voll-intelligence):

pydantic_ai.exceptions.UnexpectedModelBehavior: Invalid response from openai chat completions endpoint: 3 validation errors for ChatCompletion
choices
  Input should be a valid list [type=list_type, input_value=None, ...]
model
  Input should be a valid string [type=string_type, input_value=None, ...]
object
  Input should be 'chat.completion' [type=literal_error, input_value=None, ...]

Likely a transient provider hiccup, not something tied to the specific input.

Because UnexpectedModelBehavior is a sibling of ModelAPIError under AgentRunError (not a subclass), it silently bypasses the configured fallback-model entirely and kills the module outright — even though a fallback-model was explicitly configured for exactly this kind of situation.

Scope

Observed once in 376 generated pages on the run in question — low frequency, but the failure mode is a genuine gap: the fallback exists specifically to catch this kind of thing, and doesn't.

Fix

Pass fallback_on=(ModelAPIError, UnexpectedModelBehavior) explicitly in create_fallback_models.

🤖 Generated with Claude Code

FallbackModel's default fallback_on=(ModelAPIError,) does not cover
UnexpectedModelBehavior, which pydantic-ai raises for a 200 response whose
body doesn't match the expected schema (seen against OpenRouter: a
ChatCompletion with choices/model/object all None — likely a transient
provider hiccup, not something tied to the specific input).

Because UnexpectedModelBehavior is a sibling of ModelAPIError under
AgentRunError (not a subclass), it silently bypasses the configured
fallback-model entirely and kills the module outright, even though a
fallback-model was explicitly configured. Observed once in 376 generated
pages on a real run (voll-intelligence) — low frequency, but the failure
mode is a genuine gap: the fallback exists specifically to catch this kind
of thing, and doesn't.

Fix: pass fallback_on=(ModelAPIError, UnexpectedModelBehavior) explicitly.
…tic-ai 1.0.6)

requirements.txt pins pydantic-ai==1.0.6, and that version's
pydantic_ai.exceptions has no ModelAPIError (it was added in a later
release as a broader base class over ModelHTTPError) — only ModelHTTPError
and UnexpectedModelBehavior exist. Importing ModelAPIError broke collection
for every test module that imports llm_services, transitively or directly.

FallbackModel's own default in 1.0.6 is fallback_on=(ModelHTTPError,), so
using ModelHTTPError here instead of ModelAPIError keeps the exact same
fix intent (widen the default to also cover UnexpectedModelBehavior) while
working with the pinned dependency version.

CI: ImportError: cannot import name 'ModelAPIError' from
'pydantic_ai.exceptions' (9 collection errors).

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant