Skip to content

fix(streaming): resolve unchecked content block index and type safety issues - #1797

Closed
vjaudir8123-debug wants to merge 1 commit into
anthropics:mainfrom
vjaudir8123-debug:fix/streaming-index-and-types
Closed

fix(streaming): resolve unchecked content block index and type safety issues#1797
vjaudir8123-debug wants to merge 1 commit into
anthropics:mainfrom
vjaudir8123-debug:fix/streaming-index-and-types

Conversation

@vjaudir8123-debug

Copy link
Copy Markdown
Contributor

Summary

This PR addresses two critical bugs in the streaming message parser (_messages.py and _beta_messages.py) that can cause runtime crashes or data corruption.

1. Missing Content Block Index Validation

The parser previously had a # TODO: check index comment and blindly appended new blocks on content_block_start. If events arrived out of order or an index was skipped, the subsequent content_block_delta would either overwrite the wrong block or crash with an IndexError. This PR correctly pads the list up to event.index before inserting the block.

2. construct() Bypassing Type Validation

The snapshot initialization used Pydantics construct(**event.message.to_dict()). Because construct()skips validation and deep coercion, nested fields likeusagewere left as raw Python dictionaries rather than Pydantic objects. When a subsequent usage delta arrived,current_snapshot.usage.output_tokens = ...would crash withAttributeError: 'dict' object has no attribute 'output_tokens'. This PR fixes it by using construct_type(type_=...)`, ensuring correct instantiation of nested models.

… issues

1. Solves the `TODO: check index` by padding the content block list to the exact event index. Previously, `content_block_start` would blindly append, meaning out-of-order or skipped indices would cause data corruption or `IndexError`.
2. Replaces `ParsedMessage.construct()` with `construct_type(type_=ParsedMessage)` on `message_start`. Pydantic's `construct()` bypasses validation, which left the `usage` block as a raw dict. This would later crash the stream with `AttributeError: 'dict' object has no attribute 'output_tokens'` on subsequent usage deltas.

Co-authored-by: Claude <noreply@anthropic.com>
@vjaudir8123-debug
vjaudir8123-debug requested a review from a team as a code owner August 4, 2026 07:25
@tomer-ant

Copy link
Copy Markdown

Thanks, but see https://github.com/anthropics/anthropic-sdk-python/issues/1192#issuecomment-… — the API never sends a content_block_delta for an index without a prior content_block_start, and the reports we traced came through intermediaries rewriting the stream. We'd rather not add handling in the accumulator without a first-party reproduction. If you have a request-id from a direct call where this happens, reply on #1192.

@vjaudir8123-debug

Copy link
Copy Markdown
Contributor Author

Understood on the index checking! Makes total sense that you do not want to add defensive padding for third-party proxies.

However, this PR also included a completely separate fix for a Pydantic type safety bug. ParsedMessage.construct() bypasses type coercion, which leaves nested fields (like usage) as raw Python dictionaries rather than Pydantic objects. When a subsequent usage delta arrives, current_snapshot.usage.output_tokens = ... will crash with AttributeError: 'dict' object has no attribute 'output_tokens'.

Since that is a pure Python bug internal to the SDK (unrelated to proxies), I have extracted just the Pydantic fix into a clean, targeted PR here: #1861.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants