Skip to content

fix(anthropic): use get_final_message for robust usage extraction after stream#1872

Closed
giulio-leone wants to merge 1 commit intostrands-agents:mainfrom
giulio-leone:fix/anthropic-stream-early-termination
Closed

fix(anthropic): use get_final_message for robust usage extraction after stream#1872
giulio-leone wants to merge 1 commit intostrands-agents:mainfrom
giulio-leone:fix/anthropic-stream-early-termination

Conversation

@giulio-leone
Copy link
Contributor

Summary

Fixes #1868
Related: #1746, #1785

When the Anthropic stream terminates before emitting a message_stop event (e.g. on server disconnect or early stop), the last loop variable event may be a TextEvent that has no .message attribute, causing:

AttributeError: 'TextEvent' object has no attribute 'message'

Root Cause

After the async for event in stream loop, the code accessed event.message.usage which relies on event being the last yielded event. If the stream terminates early, event may not have a .message attribute.

Fix

Replace event.message.usage with await stream.get_final_message() which safely returns the accumulated message regardless of how the stream ended. This is the recommended Anthropic SDK pattern for extracting final metadata.

Testing

  • Updated test_stream to use a mock stream with get_final_message()
  • Added test_stream_early_termination covering the case where no recognized events are yielded before the stream closes

Both tests pass locally.

@giulio-leone giulio-leone force-pushed the fix/anthropic-stream-early-termination branch from 84bff6a to eed80a7 Compare March 13, 2026 04:34
@github-actions github-actions bot added size/xs and removed size/s labels Mar 13, 2026
@giulio-leone giulio-leone force-pushed the fix/anthropic-stream-early-termination branch from eed80a7 to 4513ce0 Compare March 15, 2026 16:12
@github-actions github-actions bot added size/xs and removed size/xs labels Mar 15, 2026
@giulio-leone
Copy link
Contributor Author

Friendly ping — this fixes Anthropic usage extraction after streaming by using get_final_message() instead of indexing into content blocks, which can miss usage data on partial responses.

…m termination

Fixes #1868

When the Anthropic API stream terminates before sending message_stop
(e.g. network timeout, connection reset), the last event in the
async for loop may not have a .message attribute, causing:

  AttributeError: 'TextEvent' object has no attribute 'message'

Replace the fragile event.message.usage access with
stream.get_final_message() which safely returns the accumulated
message snapshot regardless of how the stream ended. Falls back to
the old pattern for test/mock streams that lack this API.
@giulio-leone giulio-leone force-pushed the fix/anthropic-stream-early-termination branch from 4513ce0 to 369c5ae Compare March 23, 2026 10:33
@github-actions github-actions bot added size/xs and removed size/xs labels Mar 23, 2026
@giulio-leone
Copy link
Contributor Author

PR refresh — 2026-03-23

Cherry-picked onto current main (fd8168a5) from prior merge-base fca208b8. Branch fix/anthropic-stream-early-termination force-pushed to fork.

Test validation (double-pass):

  • tests/strands/models/test_anthropic.py
  • Pass 1: 42/42 ✅
  • Pass 2: 42/42 ✅

All tests pass. PR is ready for review.

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] AttributeError on event.message.usage when Anthropic stream terminates before message_stop

1 participant