{"record":{"id":"3e7acf6d47d3fe4a","repo":"openai/openai-python","slug":"no-messages-found","errorCode":null,"errorMessage":"No messages found","messagePattern":"No messages found","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"warning","filePath":"src/openai/lib/streaming/_assistants.py","lineNumber":131,"sourceCode":"            raise RuntimeError(\"No final run object found\")\n\n        return self.__current_run\n\n    def get_final_run_steps(self) -> list[RunStep]:\n        \"\"\"Wait for the stream to finish and returns the steps taken in this run\"\"\"\n        self.until_done()\n\n        if not self.__run_step_snapshots:\n            raise RuntimeError(\"No run steps found\")\n\n        return [step for step in self.__run_step_snapshots.values()]\n\n    def get_final_messages(self) -> list[Message]:\n        \"\"\"Wait for the stream to finish and returns the messages emitted in this run\"\"\"\n        self.until_done()\n\n        if not self.__message_snapshots:\n            raise RuntimeError(\"No messages found\")\n\n        return [message for message in self.__message_snapshots.values()]\n\n    def __text_deltas__(self) -> Iterator[str]:\n        for event in self:\n            if event.event != \"thread.message.delta\":\n                continue\n\n            for content_delta in event.data.delta.content or []:\n                if content_delta.type == \"text\" and content_delta.text and content_delta.text.value:\n                    yield content_delta.text.value\n\n    # event handlers\n\n    def on_end(self) -> None:\n        \"\"\"Fires when the stream has finished.\n\n        This happens if the stream is read to completion","sourceCodeStart":113,"sourceCodeEnd":149,"githubUrl":"https://github.com/openai/openai-python/blob/9917c6e28e66e90e1227b3d223c06a8c5441515a/src/openai/lib/streaming/_assistants.py#L113-L149","documentation":"Raised by AssistantEventHandler.get_final_messages after stream completion when __message_snapshots is empty. Messages are accumulated from thread.message.* events; if the run produced no message events (e.g. it was cancelled, failed, or only called tools), the snapshot dict is empty and this error surfaces.","triggerScenarios":"Calling get_final_messages() on a run that emitted no thread.message.created/delta events - cancelled or failed runs, runs consisting only of tool steps, invalid inputs where the stream closes early, or a custom handler that skips accumulate_event.","commonSituations":"Assistants v2 streaming with runs that end in status cancelled/failed; handlers that override on_event without chaining; expecting a message from a run that only submitted tool outputs.","solutions":["Check the final run status via get_final_run() (or __current_run.status) before asking for messages","Wrap in try/except RuntimeError and default to an empty list if absent messages are acceptable","Ensure custom event overrides call super().on_event(event) so message snapshots accumulate","Verify the thread had a user message and the run was not cancelled"],"exampleFix":"# before\nmessages = stream.get_final_messages()\n\n# after\nrun = stream.get_final_run()\nif run.status == \"completed\":\n    messages = stream.get_final_messages()\nelse:\n    messages = []\n    print(f\"run ended with status {run.status}\")","handlingStrategy":"fallback","validationCode":"null","typeGuard":"null","tryCatchPattern":"try:\n    messages = stream.get_final_messages()\nexcept RuntimeError:\n    messages = []","preventionTips":["Check the final run status before asking for messages","Chain event callbacks to the base handler","Ensure the thread contains a user message before streaming"],"tags":["assistants","streaming","messages","python"],"backgroundTag":"stream-missing-final-event","analyzedSha":"9917c6e28e66e90e1227b3d223c06a8c5441515a","analyzedAt":"2026-08-28T11:46:34.183Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}