Skip to content

fix(streaming): guard stop_* fields from being overwritten by subsequent message_delta events - #1972

Open
iosayin wants to merge 1 commit into
anthropics:mainfrom
iosayin:fix/1940-message-delta-stop-fields-guard
Open

iosayin wants to merge 1 commit into
anthropics:mainfrom
iosayin:fix/1940-message-delta-stop-fields-guard

Conversation

@iosayin

@iosayin iosayin commented Oct 4, 2026

Copy link
Copy Markdown

Fixes #1940

Summary

In streaming message accumulation (_messages.py and _beta_messages.py), subsequent message_delta events that omit stop_reason, stop_sequence, or stop_details (i.e., their delta values are None) previously overwrote the fields in current_snapshot unconditionally. This caused accumulated stop metadata from earlier deltas or start events to be reset to None.

Changes

  • Added is not None guards for event.delta.stop_reason, event.delta.stop_sequence, and event.delta.stop_details in both src/anthropic/lib/streaming/_messages.py and src/anthropic/lib/streaming/_beta_messages.py, matching the convention of container, input_transformations, and optional usage fields.
  • Added regression tests in tests/lib/streaming/test_messages.py and tests/lib/streaming/test_beta_messages.py verifying that omitting stop metadata on subsequent deltas preserves earlier values.
  • Formatted and linted with ruff.
  • Cryptographically signed commit with SSH key.

@sigley sigley left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Validated exact head c4808ae3 independently. A later usage-only message_delta currently clears an already accumulated stop_reason / stop_sequence; this head preserves those fields when the incoming delta leaves them unset, while still applying new non-null values. A two-delta synthetic sequence reproduces the loss on current main and preserves the terminal metadata on this head. The branch merges cleanly with current main, and the stable + beta streaming test slices pass 69/69. I do not see a blocking correctness issue.

This branch has not been deployed

No deployments
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.

streaming: a later message_delta that omits stop_reason resets it to None (container is guarded, the stop_* fields are not)

2 participants