Skip to content

Bug: Streaming responses don't capture response_id or model_version #5812

Open

Description

@ericapisani

Problem

In streaming.py, the accumulate_streaming_response() function initializes response_id and model to None (lines 53-54) but never populates them from the streaming chunks. The accumulation loop (lines 56-83) never reads chunk.response_id or chunk.model_version.

This means streaming responses will always have null for gen_ai.response.id and gen_ai.response.model.

The non-streaming path correctly captures both in utils.py:886-890:

if getattr(response, "response_id", None):
    span.set_data(SPANDATA.GEN_AI_RESPONSE_ID, response.response_id)
if getattr(response, "model_version", None):
    span.set_data(SPANDATA.GEN_AI_RESPONSE_MODEL, response.model_version)

Files

  • sentry_sdk/integrations/google_genai/streaming.py — accumulate_streaming_response()

Acceptance Criteria

  • Streaming chunks are checked for response_id and model_version
  • gen_ai.response.id and gen_ai.response.model are populated on streaming spans
  • Test added to verify streaming responses capture these fields

Activity

  1. linear-code commented on Mar 24, 2026

    @linear-code
  2. NIK-TIGER-BILL commented on Mar 30, 2026

    @NIK-TIGER-BILL
  3. moved this to Waiting for: Product Owner in GitHub Issues with 👀 3on Mar 30, 2026
  4. Bahtya commented on Apr 6, 2026

    @Bahtya

    I'd like to work on this. The fix is straightforward — extract response_id and model_version from streaming chunks in the accumulation loop, using getattr to safely handle missing attributes. I've identified the exact location in sentry_sdk/integrations/google_genai/streaming.py. Happy to submit a PR if this approach looks correct.

  5. moved this from Waiting for: Product Owner to No status in GitHub Issues with 👀 3on Apr 21, 2026
  6. zkasuran commented on Aug 11, 2026

    @zkasuran
    Contributor

    I hit this on 2.67.0 and verified it end to end. Would you like me to pick it up? A patch is
    ready if so.

    Confirmation that both attributes are lost on every streaming call, not just some. I ran the
    same content through the real integration twice, once as a whole GenerateContentResponse
    and once as a chunk sequence, then diffed the gen_ai.* attributes on the chat span. Six
    response shapes: plain text, reasoning plus cached tokens, a tool call, a MAX_TOKENS
    finish, metadata only on the final chunk, then no usage metadata at all.

    SUMMARY: attributes broken on the streaming path
      gen_ai.response.id                 in 6/6 cases
      gen_ai.response.model              in 6/6 cases
    

    Nothing else diverges. Text, finish reasons, tool calls and all five token counts match the
    non-streaming path in every shape, so it is just the two fields. AsyncModels.generate_content_stream
    is affected the same way.

    Also confirmed against real Gemini traffic rather than fixtures: on gemini-2.5-flash every
    chunk carries both response_id and model_version (4/4 chunks) and the values are stable
    across the stream. Worth knowing for the accumulation rule, because modelVersion is not
    always the requested id. Asking for gemini-flash-latest returned model_version of
    gemini-3.6-flash, which is exactly the case gen_ai.response.model is there to record.

    Two notes on the fix if it is useful:

    Reading the last non-None value rather than the first matters. Gemini repeats both fields on
    every chunk in real traffic, but this repo's own streaming fixture puts them on the first chunk
    only, so a first-wins read would pass the tests while a chunk that omits the field would still
    be able to clear a good value under last-wins-without-guard. model = event.message.model or model
    in the anthropic integration is the same convention.

    The streaming fixture at tests/integrations/google_genai/test_google_genai.py already carries
    "responseId": "response-id-stream-123" and "modelVersion": "gemini-1.5-flash", so the data
    is already on the way in. No streaming test asserts either attribute reaches the span, which is
    why 510 passing tests did not catch this. Adding those two assertions to the existing streaming
    test makes it fail before the fix, plus one new async streaming test where only the first chunk
    carries the metadata.

    I have the change, the two assertions and the async test locally against 3fbf49b with the
    google_genai suite green (511 passed, 1 skipped), ruff check and ruff format clean, and
    mypy sentry_sdk showing no new errors. Happy to open the PR once a maintainer confirms the
    approach, per CONTRIBUTING.

  7. moved this to Waiting for: Product Owner in GitHub Issues with 👀 3on Aug 11, 2026
  8. moved this from Waiting for: Product Owner to No status in GitHub Issues with 👀 3on Sep 15, 2026
  9. sentry-junior commented on Nov 12, 2026

    @sentry-junior
    Contributor

    Reproduced in getsentry/repro#71. Draft fix #8260 was closed without merging.

  10. added
    Junior: reproJunior reproduces this bug and drafts a fix
    and removed
    Junior: reproJunior reproduces this bug and drafts a fix
    on Nov 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions