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).

Solutions

  1. Ensure the handler processes every event from the start of the stream (do not drop thread.message.created)
  2. In custom pipelines, call accumulate_event for all events in arrival order and keep the returned snapshot
  3. If resuming a stream, seed current_message_snapshot from the message created event or skip delta accumulation until created arrives
  4. 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

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


AI-assisted analysis of openai/openai-python@9917c6e28e (2026-08-28). Data as JSON: /api/errors/4752c90703de8cbe. Report an issue: GitHub.

Appendix: 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)