{"record":{"id":"cfa4429b545eba3c","repo":"openai/openai-python","slug":"no-final-run-object-found","errorCode":null,"errorMessage":"No final run object found","messagePattern":"No final run object found","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"src/openai/lib/streaming/_assistants.py","lineNumber":113,"sourceCode":"    def close(self) -> None:\n        \"\"\"\n        Close the response and release the connection.\n\n        Automatically called when the context manager exits.\n        \"\"\"\n        if self.__stream:\n            self.__stream.close()\n\n    def until_done(self) -> None:\n        \"\"\"Waits until the stream has been consumed\"\"\"\n        consume_sync_iterator(self)\n\n    def get_final_run(self) -> Run:\n        \"\"\"Wait for the stream to finish and returns the completed Run object\"\"\"\n        self.until_done()\n\n        if not self.__current_run:\n            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\")","sourceCodeStart":95,"sourceCodeEnd":131,"githubUrl":"https://github.com/openai/openai-python/blob/9917c6e28e66e90e1227b3d223c06a8c5441515a/src/openai/lib/streaming/_assistants.py#L95-L131","documentation":"Raised by AssistantEventHandler.get_final_run after the stream is fully consumed. It means the stream completed without the handler ever storing a Run object in __current_run, which normally happens when a thread.run.* event carrying run data is processed. Typically the run never actually started or the stream ended before any run snapshot arrived.","triggerScenarios":"Calling stream.get_final_run() on an Assistants v2 run stream that produced no thread.run.created/queued/in_progress events - e.g. streaming with an invalid assistant_id or thread_id where the server closes the stream early, or consuming the stream after it errored client-side so run events were never accumulated.","commonSituations":"Using the Assistants streaming API (v2 beta) and calling get_final_run after until_done; runs cancelled server-side immediately; malformed thread/assistant ids; the API silently terminating the SSE stream.","solutions":["Inspect the raw events: override on_event or iterate stream to see which thread.run.* events actually arrived","Verify thread_id and assistant_id are valid and the run was accepted (check for APIError during streaming)","If you need resilience, call get_final_run inside try/except RuntimeError and fall back to client.beta.threads.runs.retrieve(run_id)","Upgrade the SDK - older builds had gaps in run event accumulation"],"exampleFix":"# before\nrun = stream.get_final_run()\n\n# after\ntry:\n    run = stream.get_final_run()\nexcept RuntimeError:\n    run = client.beta.threads.runs.retrieve(thread_id=thread_id, run_id=run_id)","handlingStrategy":"try-catch","validationCode":"null","typeGuard":"null","tryCatchPattern":"try:\n    run = stream.get_final_run()\nexcept RuntimeError as e:\n    if \"No final run object\" in str(e):\n        run = client.beta.threads.runs.retrieve(thread_id=thread_id, run_id=run_id)","preventionTips":["Verify thread_id and assistant_id before starting the run","Log raw events during development to confirm run events arrive","Handle APIError raised while iterating the stream"],"tags":["assistants","streaming","run","final-result","python"],"backgroundTag":"stream-missing-final-event","analyzedSha":"9917c6e28e66e90e1227b3d223c06a8c5441515a","analyzedAt":"2026-08-28T11:46:34.183Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}