{"record":{"id":"2506c00330399727","repo":"huggingface/smolagents","slug":"unexpected-api-response-model-self-model-id-r","errorCode":null,"errorMessage":"Unexpected API response: model '{self.model_id}' returned no choices.  This may indicate a possible API or upstream issue. Response details: {response.model_dump()}","messagePattern":"Unexpected API response: model '(.+?)' returned no choices\\.  This may indicate a possible API or upstream issue\\. Response details: (.+?)","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"src/smolagents/models.py","lineNumber":1290,"sourceCode":"        **kwargs,\n    ) -> ChatMessage:\n        completion_kwargs = self._prepare_completion_kwargs(\n            messages=messages,\n            stop_sequences=stop_sequences,\n            response_format=response_format,\n            tools_to_call_from=tools_to_call_from,\n            model=self.model_id,\n            api_base=self.api_base,\n            api_key=self.api_key,\n            convert_images_to_image_urls=True,\n            custom_role_conversions=self.custom_role_conversions,\n            **kwargs,\n        )\n        self._apply_rate_limit()\n        response = self.retryer(self.client.completion, **completion_kwargs)\n\n        if not response.choices:\n            raise RuntimeError(\n                f\"Unexpected API response: model '{self.model_id}' returned no choices. \"\n                \" This may indicate a possible API or upstream issue. \"\n                f\"Response details: {response.model_dump()}\"\n            )\n        content = response.choices[0].message.content\n        if stop_sequences is not None and not self.supports_stop_parameter:\n            content = remove_content_after_stop_sequences(content, stop_sequences)\n        return ChatMessage(\n            role=response.choices[0].message.role,\n            content=content,\n            tool_calls=response.choices[0].message.tool_calls,\n            raw=response,\n            token_usage=TokenUsage(\n                input_tokens=response.usage.prompt_tokens,\n                output_tokens=response.usage.completion_tokens,\n            ),\n        )\n","sourceCodeStart":1272,"sourceCodeEnd":1308,"githubUrl":"https://github.com/huggingface/smolagents/blob/30bb1161095dbae2271e6bc3cc4c219cc3897a57/src/smolagents/models.py#L1272-L1308","documentation":"LiteLLMModel.generate raises this RuntimeError when the LiteLLM completion call succeeds at the transport level but the returned response object contains an empty `choices` list. smolagents expects at least one choice to extract `response.choices[0].message.content`, so an empty list means it cannot proceed. It dumps the full response via `model_dump()` to help diagnose whether the upstream provider returned an error payload or a malformed body.","triggerScenarios":"Calling model(...) or generate(...) on LiteLLMModel where the provider (e.g. an OpenAI-compatible endpoint, Azure, or a proxied model) returns 200 with no choices; LiteLLM sometimes swallows upstream errors (rate limits, content filter blocks, provider outages) into an empty-choices response instead of raising.","commonSituations":"Misconfigured base_url/model_id pointing at an endpoint that returns an empty body; upstream provider outage or content moderation blocking; LiteLLM version changes altering error propagation; using a model name the router/deployment does not actually serve.","solutions":["Inspect the Response details in the message: if it contains an error field, address that upstream error (auth, rate limit, content filter).","Verify model_id and api_base are correct and that the model is actually deployed/served.","Reproduce with `litellm.completion(...)` directly to see whether LiteLLM or the provider drops the choices.","Upgrade/downgrade litellm to a known-good version; empty-choices behavior varies across releases.","Wrap agent/model calls in retry logic (smolagents models support a retryer) to ride out transient upstream failures."],"exampleFix":"# before\nmodel = LiteLLMModel(model_id=\"my-model\", api_base=\"http://localhost:8000\")\nout = model([{\"role\": \"user\", \"content\": \"hi\"}])  # RuntimeError: returned no choices\n\n# after\nimport litellm\nresp = litellm.completion(model=\"my-model\", api_base=\"http://localhost:8000\", messages=[{\"role\":\"user\",\"content\":\"hi\"}])\nprint(resp)  # inspect what the endpoint actually returns; fix deployment/auth accordingly","handlingStrategy":"try-catch","validationCode":"import litellm\nresp = litellm.completion(model=model_id, api_base=base_url, messages=[{\"role\":\"user\",\"content\":\"ping\"}])\nassert resp.choices, f\"endpoint returned no choices: {resp}\"","typeGuard":"def has_choices(resp) -> bool:\n    return bool(getattr(resp, \"choices\", None))","tryCatchPattern":"try:\n    out = model(messages)\nexcept RuntimeError as e:\n    if \"returned no choices\" in str(e):\n        logger.error(\"Upstream issue, inspect response details: %s\", e)\n        out = model(messages)  # or back off / switch model\n    else:\n        raise","preventionTips":["Run a one-shot litellm.completion smoke test against the endpoint at startup.","Pin litellm to a tested version.","Configure the model retryer for transient upstream failures.","Log full response details when this fires to identify provider-level causes."],"tags":["litellm","smolagents","empty-response","upstream","llm-provider"],"backgroundTag":"llm-api-empty-choices-response","analyzedSha":"30bb1161095dbae2271e6bc3cc4c219cc3897a57","analyzedAt":"2026-08-28T18:52:54.169Z","schemaVersion":2},"datasetVersion":"2026-08-28T21:17:43.275Z"}