openai/openai-python · warning · RuntimeError
No run steps found
Error message
No run steps found
What it means
Raised by AssistantEventHandler.get_final_run_steps after stream completion when __run_step_snapshots is empty. Run steps are accumulated from thread.run.step.* events; if none arrived (the run produced no tool calls/details, or the stream never delivered run-step events), the dict stays empty and this error is thrown.
Source
Thrown at src/openai/lib/streaming/_assistants.py:122
def until_done(self) -> None:
"""Waits until the stream has been consumed"""
consume_sync_iterator(self)
def get_final_run(self) -> Run:
"""Wait for the stream to finish and returns the completed Run object"""
self.until_done()
if not self.__current_run:
raise RuntimeError("No final run object found")
return self.__current_run
def get_final_run_steps(self) -> list[RunStep]:
"""Wait for the stream to finish and returns the steps taken in this run"""
self.until_done()
if not self.__run_step_snapshots:
raise RuntimeError("No run steps found")
return [step for step in self.__run_step_snapshots.values()]
def get_final_messages(self) -> list[Message]:
"""Wait for the stream to finish and returns the messages emitted in this run"""
self.until_done()
if not self.__message_snapshots:
raise RuntimeError("No messages found")
return [message for message in self.__message_snapshots.values()]
def __text_deltas__(self) -> Iterator[str]:
for event in self:
if event.event != "thread.message.delta":
continue
for content_delta in event.data.delta.content or []:View on GitHub (pinned to 9917c6e28e)
Solutions
- Treat empty steps as valid: wrap in try/except RuntimeError and use an empty list
- If you override event callbacks in a subclass, call super().on_event(event) (or accumulate_event) so snapshots are recorded
- Verify with get_final_run() that the run actually completed successfully
- Check that tool use was actually expected for this run
Example fix
# before
steps = stream.get_final_run_steps()
# after
try:
steps = stream.get_final_run_steps()
except RuntimeError:
steps = [] # run had no tool steps Defensive patterns
Strategy: fallback
Validate before calling
null
Type guard
null
Try / catch
try:
steps = stream.get_final_run_steps()
except RuntimeError:
steps = [] # no tool steps in this run Prevention
- Call super().on_event(event) in custom handler overrides
- Expect empty steps for tool-free runs
- Check run status before requesting derived results
When it happens
Trigger: Calling get_final_run_steps() on a simple run that only produced a text message (no tool steps), or on a stream that terminated before any thread.run.step.* events were emitted; also when custom on_event overrides skip the accumulate_event call.
Common situations: Assistants v2 streaming where the model answered directly with no tools; custom handler subclasses overriding on_event without calling super(); interrupted or cancelled runs.
Related errors
- A single event handler cannot be shared between multiple str
- No final run object found
- No messages found
- Stream has not been started yet
- Encountered a message delta with no previous snapshot
AI-assisted analysis of openai/openai-python@9917c6e28e (2026-08-28).
Data as JSON: /api/errors/59b3f471b26e9115.
Report an issue: GitHub.