{"record":{"id":"4752c90703de8cbe","repo":"openai/openai-python","slug":"encountered-a-message-delta-with-no-previous-snaps","errorCode":null,"errorMessage":"Encountered a message delta with no previous snapshot","messagePattern":"Encountered a message delta with no previous snapshot","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"src/openai/lib/streaming/_assistants.py","lineNumber":940,"sourceCode":"    return None\n\n\ndef accumulate_event(\n    *,\n    event: AssistantStreamEvent,\n    current_message_snapshot: Message | None,\n) -> tuple[Message | None, list[MessageContentDelta]]:\n    \"\"\"Returns a tuple of message snapshot and newly created text message deltas\"\"\"\n    if event.event == \"thread.message.created\":\n        return event.data, []\n\n    new_content: list[MessageContentDelta] = []\n\n    if event.event != \"thread.message.delta\":\n        return current_message_snapshot, []\n\n    if not current_message_snapshot:\n        raise RuntimeError(\"Encountered a message delta with no previous snapshot\")\n\n    data = event.data\n    if data.delta.content:\n        for content_delta in data.delta.content:\n            try:\n                block = current_message_snapshot.content[content_delta.index]\n            except IndexError:\n                current_message_snapshot.content.insert(\n                    content_delta.index,\n                    cast(\n                        MessageContent,\n                        construct_type(\n                            # mypy doesn't allow Content for some reason\n                            type_=cast(Any, MessageContent),\n                            value=model_dump(content_delta, exclude_unset=True, warnings=False),\n                        ),\n                    ),\n                )","sourceCodeStart":922,"sourceCodeEnd":958,"githubUrl":"https://github.com/openai/openai-python/blob/9917c6e28e66e90e1227b3d223c06a8c5441515a/src/openai/lib/streaming/_assistants.py#L922-L958","documentation":"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).","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"# before\ndef on_event(self, event):\n    if event.event == \"thread.message.delta\":\n        self.accumulate_event(event)  # created was skipped\n\n# after\ndef on_event(self, event):\n    self.accumulate_event(event)  # process every event in order","handlingStrategy":"validation","validationCode":"def can_apply_delta(event, snapshot) -> bool:\n    return not (event.event == \"thread.message.delta\" and snapshot is None)","typeGuard":"def is_message_delta_with_base(event, current_snapshot) -> bool:\n    return event.event == \"thread.message.delta\" and current_snapshot is not None","tryCatchPattern":"try:\n    snapshot, _ = accumulate_event(event, snapshot)\nexcept RuntimeError as e:\n    if \"no previous snapshot\" in str(e):\n        snapshot = None  # wait for thread.message.created before accumulating","preventionTips":["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"],"tags":["assistants","streaming","delta-accumulation","event-ordering","python"],"backgroundTag":"delta-without-base-snapshot","analyzedSha":"9917c6e28e66e90e1227b3d223c06a8c5441515a","analyzedAt":"2026-08-28T11:46:34.183Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}