{"record":{"id":"cd545e1835204823","repo":"browser-use/browser-use","slug":"failed-to-parse-structured-output-from-model-respo-cd545e","errorCode":null,"errorMessage":"Failed to parse structured output from model response","messagePattern":"Failed to parse structured output from model response","errorType":"exception","errorClass":"ModelProviderError","httpStatus":500,"severity":"error","filePath":"browser_use/llm/openrouter/chat.py","lineNumber":189,"sourceCode":"\t\t\t\t}\n\n\t\t\t\t# Return structured response\n\t\t\t\tresponse = await self.get_client().chat.completions.create(\n\t\t\t\t\tmodel=self.model,\n\t\t\t\t\tmessages=openrouter_messages,\n\t\t\t\t\ttemperature=self.temperature,\n\t\t\t\t\ttop_p=self.top_p,\n\t\t\t\t\tseed=self.seed,\n\t\t\t\t\tresponse_format=ResponseFormatJSONSchema(\n\t\t\t\t\t\tjson_schema=response_format_schema,\n\t\t\t\t\t\ttype='json_schema',\n\t\t\t\t\t),\n\t\t\t\t\textra_headers=extra_headers,\n\t\t\t\t\t**(self.extra_body or {}),\n\t\t\t\t)\n\n\t\t\t\tif response.choices[0].message.content is None:\n\t\t\t\t\traise ModelProviderError(\n\t\t\t\t\t\tmessage='Failed to parse structured output from model response',\n\t\t\t\t\t\tstatus_code=500,\n\t\t\t\t\t\tmodel=self.name,\n\t\t\t\t\t)\n\t\t\t\tusage = self._get_usage(response)\n\n\t\t\t\tparsed = output_format.model_validate_json(response.choices[0].message.content)\n\n\t\t\t\treturn ChatInvokeCompletion(\n\t\t\t\t\tcompletion=parsed,\n\t\t\t\t\tusage=usage,\n\t\t\t\t)\n\n\t\texcept RateLimitError as e:\n\t\t\traise ModelRateLimitError(message=e.message, model=self.name) from e\n\n\t\texcept APIConnectionError as e:\n\t\t\traise ModelProviderError(message=str(e), model=self.name) from e","sourceCodeStart":171,"sourceCodeEnd":207,"githubUrl":"https://github.com/browser-use/browser-use/blob/6c73fced2f6d45a11d88622fe56365a5fe18f28b/browser_use/llm/openrouter/chat.py#L171-L207","documentation":"OpenRouter chat wrapper's structured-output path: after a successful completion, if `response.choices[0].message.content is None` it raises ModelProviderError (500) because there is no JSON text to feed `output_format.model_validate_json`. OpenRouter routes to many upstream providers, and some return null content (reasoning-only, tool-call-only, or upstream errors mapped to empty content).","triggerScenarios":"Calling ChatOpenRouter with an `output_format` where the routed model returns null content — common with free-tier or non-JSON-native models, models that answer via tool_calls, or upstream providers whose JSON mode is unimplemented. Also occurs when OpenRouter routes to a model that spent its output on hidden reasoning.","commonSituations":"Using `:free` OpenRouter models that don't support structured output; picking a model variant without JSON-mode support; hitting an upstream content filter; upstream provider flakiness returning empty completions.","solutions":["Switch the OpenRouter model slug to one with native structured-output/JSON support (e.g. major frontier models) and re-run","Retry once — transient null-content responses from upstream providers are common on OpenRouter","Check the OpenRouter dashboard/logs for the upstream finish_reason (filter, length, tool_calls) for that request","Avoid `:free` variants for structured output; use the paid tier of the same model"],"exampleFix":"# before\nllm = ChatOpenRouter(model='some-model:free')\n# after\nllm = ChatOpenRouter(model='openai/gpt-4.1-mini')","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"try:\n    out = await llm.invoke(msgs, output_format=Schema)\nexcept ModelProviderError as e:\n    if 'parse structured output' in e.message:\n        llm.model = FALLBACK_MODEL  # e.g. a frontier model with native JSON mode\n        out = await llm.invoke(msgs, output_format=Schema)\n    else:\n        raise","preventionTips":["Avoid ':free' OpenRouter models for structured output","Keep a known-good fallback model slug for schema-driven calls"],"tags":["openrouter","structured-output","empty-content","model-routing"],"backgroundTag":null,"analyzedSha":"6c73fced2f6d45a11d88622fe56365a5fe18f28b","analyzedAt":"2026-08-14T19:42:40.557Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}