openai/openai-python · error · RuntimeError
Encountered a message delta with no previous snapshot
Error message
Encountered a message delta with no previous snapshot
What it means
Raised in accumulate_event when a thread.message.delta event arrives while current_message_snapshot is None. Deltas are incremental patches meant to be applied on top of a thread.message.created snapshot; a delta with no preceding snapshot means the handler missed the creation event (it joined mid-stream, skipped events, or the server sent events out of order).
Source
Thrown at src/openai/lib/streaming/_assistants.py:940
return None
def accumulate_event(
*,
event: AssistantStreamEvent,
current_message_snapshot: Message | None,
) -> tuple[Message | None, list[MessageContentDelta]]:
"""Returns a tuple of message snapshot and newly created text message deltas"""
if event.event == "thread.message.created":
return event.data, []
new_content: list[MessageContentDelta] = []
if event.event != "thread.message.delta":
return current_message_snapshot, []
if not current_message_snapshot:
raise RuntimeError("Encountered a message delta with no previous snapshot")
data = event.data
if data.delta.content:
for content_delta in data.delta.content:
try:
block = current_message_snapshot.content[content_delta.index]
except IndexError:
current_message_snapshot.content.insert(
content_delta.index,
cast(
MessageContent,
construct_type(
# mypy doesn't allow Content for some reason
type_=cast(Any, MessageContent),
value=model_dump(content_delta, exclude_unset=True, warnings=False),
),
),
)View on GitHub (pinned to 9917c6e28e)
Solutions
- Ensure the handler processes every event from the start of the stream (do not drop thread.message.created)
- In custom pipelines, call accumulate_event for all events in arrival order and keep the returned snapshot
- If resuming a stream, seed current_message_snapshot from the message created event or skip delta accumulation until created arrives
- Capture and inspect the event sequence to confirm ordering
Example fix
# before
def on_event(self, event):
if event.event == "thread.message.delta":
self.accumulate_event(event) # created was skipped
# after
def on_event(self, event):
self.accumulate_event(event) # process every event in order Defensive patterns
Strategy: validation
Validate before calling
def can_apply_delta(event, snapshot) -> bool:
return not (event.event == "thread.message.delta" and snapshot is None) Type guard
def is_message_delta_with_base(event, current_snapshot) -> bool:
return event.event == "thread.message.delta" and current_snapshot is not None Try / catch
try:
snapshot, _ = accumulate_event(event, snapshot)
except RuntimeError as e:
if "no previous snapshot" in str(e):
snapshot = None # wait for thread.message.created before accumulating Prevention
- Process every event in arrival order from stream start
- Never filter out thread.message.created in custom handlers
- When replaying logs, start from the first event of the run
When it happens
Trigger: Streaming a run where the thread.message.created event was not processed before thread.message.delta - e.g. a custom handler that filters out or skips creation events, resuming/attaching to an in-flight stream, or manually feeding events into accumulate_event starting from a delta.
Common situations: Custom on_event overrides that selectively forward events to accumulate_event; replaying captured SSE event logs starting mid-stream; server-side event reordering in long runs.
Related errors
- A single event handler cannot be shared between multiple str
- No final run object found
- No run steps found
- No messages found
- Stream has not been started yet
AI-assisted analysis of openai/openai-python@9917c6e28e (2026-08-28).
Data as JSON: /api/errors/4752c90703de8cbe.
Report an issue: GitHub.