{"record":{"id":"22068bbf27bbfe25","repo":"Aider-AI/aider","slug":"no-data-found-in-llm-response","errorCode":null,"errorMessage":"No data found in LLM response!","messagePattern":"No data found in LLM response!","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"aider/coders/base_coder.py","lineNumber":1880,"sourceCode":"            except AttributeError:\n                reasoning_content = None\n\n        try:\n            self.partial_response_content = completion.choices[0].message.content or \"\"\n        except AttributeError as content_err:\n            show_content_err = content_err\n\n        resp_hash = dict(\n            function_call=str(self.partial_response_function_call),\n            content=self.partial_response_content,\n        )\n        resp_hash = hashlib.sha1(json.dumps(resp_hash, sort_keys=True).encode())\n        self.chat_completion_response_hashes.append(resp_hash.hexdigest())\n\n        if show_func_err and show_content_err:\n            self.io.tool_error(show_func_err)\n            self.io.tool_error(show_content_err)\n            raise Exception(\"No data found in LLM response!\")\n\n        show_resp = self.render_incremental_response(True)\n\n        if reasoning_content:\n            formatted_reasoning = format_reasoning_content(\n                reasoning_content, self.reasoning_tag_name\n            )\n            show_resp = formatted_reasoning + show_resp\n\n        show_resp = replace_reasoning_tags(show_resp, self.reasoning_tag_name)\n\n        self.io.assistant_output(show_resp, pretty=self.show_pretty())\n\n        if (\n            hasattr(completion.choices[0], \"finish_reason\")\n            and completion.choices[0].finish_reason == \"length\"\n        ):\n            raise FinishReasonLength()","sourceCodeStart":1862,"sourceCodeEnd":1898,"githubUrl":"https://github.com/Aider-AI/aider/blob/5dc9490bb35f9729ef2c95d00a19ccd30c26339c/aider/coders/base_coder.py#L1862-L1898","documentation":"Raised in BaseCoder's response-processing path when BOTH attribute probes on the LLM completion message failed: completion.choices[0].message.tool_calls raised AttributeError AND completion.choices[0].message.content raised AttributeError. That means the chat completion object has neither tool calls nor textual content, so there is nothing to show or apply. It is a plain Exception (not a typed error), signalling an empty/malformed API response.","triggerScenarios":"A chat completion arrives where choices[0].message lacks both 'content' and 'tool_calls' — typically from a non-OpenAI-compatible gateway, a response truncated by length limits, a content-filtered response, or a caching/mock layer returning a bare object. Also hit when the response represents only reasoning/abort fields with no message payload.","commonSituations":"Using an OpenAI-compatible proxy or local model server whose schema drifts from the OpenAI SDK (missing attributes); empty responses from content filters; streaming assembled into an incomplete message; bugs in custom LLM middleware or recorded-fixture replays in tests.","solutions":["Log the raw completion (self.verbose / print(completion)) to see which fields the provider actually returned.","Verify provider compatibility: the endpoint must return OpenAI-shaped messages with content or tool_calls on choices[0].message.","Retry the request — transient empty responses from proxies/self-hosted servers often succeed on resend.","If using a custom LiteLLM/aider model mapping, check the model config (API base, model name) points at a truly OpenAI-compatible API.","Upgrade aider and the openai SDK; schema handling of reasoning_content vs content changed across versions."],"exampleFix":"# before\n# rely on the raw exception\ntry:\n    coder.run_one(user_msg)\nexcept Exception as e:\n    print(e)  # \"No data found in LLM response!\"\n\n# after\n# inspect what the provider actually returns before blaming the prompt\ncompletion = client.chat.completions.create(...)\nmsg = completion.choices[0].message\nassert getattr(msg, \"content\", None) or getattr(msg, \"tool_calls\", None), completion.model_dump()","handlingStrategy":"try-catch","validationCode":"def completion_has_data(completion) -> bool:\n    try:\n        msg = completion.choices[0].message\n    except (IndexError, AttributeError):\n        return False\n    return bool(getattr(msg, \"content\", None)) or bool(getattr(msg, \"tool_calls\", None))","typeGuard":"def is_usable_completion(c) -> bool:\n    \"\"\"True if the completion carries content or tool calls.\"\"\"\n    msgs = getattr(getattr(c, \"choices\", None) or [None], \"__getitem__\", lambda i: None)(0)\n    m = getattr(msgs, \"message\", None)\n    return bool(m) and (bool(getattr(m, \"content\", None)) or bool(getattr(m, \"tool_calls\", None)))","tryCatchPattern":"try:\n    coder.send(new_message)\nexcept Exception as e:\n    if str(e) == \"No data found in LLM response!\":\n        # empty/malformed provider response — safe to retry once, then report\n        coder.send(new_message)\n    else:\n        raise","preventionTips":["Smoke-test third-party OpenAI-compatible endpoints with a one-shot completion and assert content is present before starting a session.","Enable coder.verbose to dump raw completions when integrating a new provider.","Keep the openai SDK and aider versions aligned with the provider's schema; watch for proxies that strip message fields."],"tags":["aider","llm-response","api-compatibility","runtime"],"backgroundTag":null,"analyzedSha":"5dc9490bb35f9729ef2c95d00a19ccd30c26339c","analyzedAt":"2026-08-15T05:40:10.498Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}