Bug Smash: restoring dropped Gemini chat config in Sentry's…
    Neura Market
    Neura Market
    /CoPilot
    Marketplace
    Directories
    Resources
    CoPilot
    ChatGPTChatGPTClaudeClaudeGeminiGeminiCursorCursorGrokGrokPerplexityPerplexityDeepSeekDeepSeekCoPilotCoPilotStable DiffusionStable DiffusionMidjourneyMidjourney
    OverviewRulesPromptsMCPsAgentsGamesBlogVideosGuidesCoursesCommunityPluginsTrending
    CoPilotBlogBug Smash: restoring dropped Gemini chat config in Sentry's JavaScript SDK
    Back to Blog
    Bug Smash: restoring dropped Gemini chat config in Sentry's JavaScript SDK
    devchallenge

    Bug Smash: restoring dropped Gemini chat config in Sentry's JavaScript SDK

    Asuran August 12, 2026
    0 views

    This is a submission for DEV's Summer Bug Smash: Clear the Lineup powered by Sentry. ...


    title: "Bug Smash: restoring dropped Gemini chat config in Sentry's JavaScript SDK" published: true tags: devchallenge, bugsmash, javascript, ai cover_image: https://dev-to-uploads.s3.us-east-2.amazonaws.com/uploads/articles/phtsf88z8k2rwycqcfd3.png

    This is a submission for DEV's Summer Bug Smash: Clear the Lineup powered by Sentry.

    Project Overview

    Sentry's JavaScript SDK auto-instruments Google GenAI so every Gemini call shows up as a span in your trace, with the model, the generation config and the system instruction attached. This entry fixes a silent regression in that instrumentation: chat calls were dropping the configuration they ran with, so the trace no longer told you how the model was set up. The fix is one focused change in @sentry/server-utils. It ships with unit tests. I verified it end to end against the live Gemini API.

    Bug Fix or Performance Improvement

    This is a bug fix for getsentry/sentry-javascript#20086, filed by a Sentry maintainer.

    The Google GenAI SDK splits a chat into two steps. First chats.create({ model, config }) builds a local chat object, where config holds temperature, top_p, top_k, max output tokens, the penalties, the tool list and the system instruction. That step does not call the model. Then chat.sendMessage(...) and chat.sendMessageStream(...) are the real model calls. The SDK reuses the create-time config for every one of them.

    Sentry used to emit a span for chats.create() and read the config off it. A refactor (#19990) removed that span because it was not a real model call, which was correct, but the config it captured went away with it. From then on the chat.sendMessage() and chat.sendMessageStream() spans only saw the per-call message, so gen_ai.request.temperature, top_p, top_k, max_tokens, the penalties, available_tools and gen_ai.system_instructions silently vanished from the trace. That PR even called out the risk in its own description and left it as a follow-up, which is exactly this issue.

    Root cause: the deep proxy that instruments the client re-proxies the chat object returned by chats.create() but discards that call's arguments, so the code that builds the message spans never sees the config.

    Code

    The fix, as a PR: getsentry/sentry-javascript#23316, branch fix/google-genai-chat-config-attrs.

    The fix captures the chats.create() arguments and welds model plus config onto each message span. The create-time config is the default. A per-message config replaces it wholesale for that request, matching how the @google/genai SDK resolves config as params.config ?? chat.config.

    function mergeChatCreateParams(
      chatCreateParams: Record<string, unknown> | undefined,
      callParams: Record<string, unknown> | undefined,
    ): Record<string, unknown> | undefined {
      if (!chatCreateParams) {
        return callParams;
      }
    
      const merged: Record<string, unknown> = { ...callParams };
    
      if (!('model' in merged) && 'model' in chatCreateParams) {
        merged.model = chatCreateParams.model;
      }
    
      // @google/genai sends `params.config ?? chat.config`, so a per-message config replaces the
      // create-time config wholesale rather than merging into it. Fall back to the create-time config
      // only when the message did not carry one, otherwise the span reports fields that were not sent.
      const callConfig = asConfigObject(callParams?.config);
      if (!callConfig) {
        const createConfig = asConfigObject(chatCreateParams.config);
        if (createConfig) {
          merged.config = createConfig;
        }
      }
    
      return merged;
    }
    

    The proxy now threads that context. When it re-proxies the chat returned by chats.create(), it passes the create arguments down. instrumentMethod builds its span attributes from the merged params:

    // in createDeepProxy, when re-proxying the chats.create() result:
    return createDeepProxy(result as object, instrumentedMethod.proxyResultPath, options, args[0]);
    
    // in instrumentMethod:
    const attributeParams = mergeChatCreateParams(chatCreateParams, params);
    const requestAttributes = extractRequestAttributes(operationName, attributeParams, context);
    

    The real method still runs on its original arguments, so nothing about the request to Google changes. Non-chat calls like models.generateContent never receive the chat context, so they are untouched.

    My Improvements

    I added the merge helper, threaded the create context through the proxy and the two branches of instrumentMethod (streaming and non-streaming). I left the create history off the message spans on purpose since it is conversation seed, not per-message input.

    I wrote a new test file with four cases: config welded onto sendMessage spans, config welded onto sendMessageStream spans, a per-message config replacing the create config, plus no leakage onto models.generateContent spans. On the unfixed code three of the four fail because the attributes are undefined. On the fix all four pass.

    Gates, all real: the @sentry/server-utils suite went from 38 files / 335 tests to 39 files / 339 tests, all passing. oxlint --type-aware and oxfmt --check are clean on the change. tsc on the source types passes. The only tsc test-config errors are pre-existing ones in unrelated files that this change never touches.

    Best Use of Sentry

    This is the kind of fix that makes AI tracing trustworthy. Sentry's AI Agents view leans on the gen_ai.* span attributes to show how each model call was configured. A chat span that is missing its temperature, its token limit and its system instruction hides the settings that actually shaped the answer. When you are debugging a bad response or a cost spike, "what config was this call running with" is the first question. Before this fix the chat spans could not answer it. Restoring the attributes puts the full picture back in the trace, consistent with what the non-chat generateContent spans already report.

    Best Use of Google AI

    I reproduced the bug and the fix against the real Gemini API, not a mock. The script builds a real @google/genai v1.20.0 client, wraps it with the actual SDK instrumentation, runs it through a real Sentry client with tracing, then reads the captured span. It calls chats.create with a full config and a system instruction, then sendMessage with a prompt.

    model: gemini-2.5-flash
    create config: temperature 0.8, topP 0.9, topK 40, maxOutputTokens 512,
                   systemInstruction "You are a friendly robot who likes to be funny."
    prompt: "Tell me a one-line joke about debugging."
    
    BEFORE the fix (chat.sendMessage span):
      PRESENT  gen_ai.request.model = "gemini-2.5-flash"
      MISSING  gen_ai.request.temperature   (dropped)
      MISSING  gen_ai.request.top_p         (dropped)
      MISSING  gen_ai.request.top_k         (dropped)
      MISSING  gen_ai.request.max_tokens    (dropped)
      MISSING  gen_ai.system_instructions   (dropped)
    
    AFTER the fix (chat.sendMessage span):
      PRESENT  gen_ai.request.model = "gemini-2.5-flash"
      PRESENT  gen_ai.request.temperature = 0.8
      PRESENT  gen_ai.request.top_p = 0.9
      PRESENT  gen_ai.request.top_k = 40
      PRESENT  gen_ai.request.max_tokens = 512
      PRESENT  gen_ai.system_instructions = "[{\"type\":\"text\",\"content\":\"You are a friendly robot who likes to be funny.\"}]"
    

    Both runs got a real Gemini reply. The AFTER run answered: "Why did the programmer quit his job debugging code? Because he kept finding himself in an infinite loop." Same call, same live model. The fix is the difference between a trace that records the chat configuration and one that quietly loses it.

    AI disclosure

    AI assistance (Claude, Anthropic) was used in developing this change. The design, the review and the verification were done by me. Before submitting I ran the @sentry/server-utils test suite (339 passing), confirmed the new test fails on the unfixed code and passes on the fix, ran oxlint --type-aware, oxfmt --check and tsc on the source types, then did a real Gemini chats.create plus sendMessage run showing the attributes dropped before the fix and present after.

    Tags

    devchallengebugsmashjavascriptai

    Comments

    More Blog

    View all
    Reviving Open Source Giants: How I Brought Weave Scope Back with Multi-Platform Docker Support in One Afternoon Using Antigravityopensource

    Reviving Open Source Giants: How I Brought Weave Scope Back with Multi-Platform Docker Support in One Afternoon Using Antigravity

    How to rescue abandoned open-source projects, modernize build systems, and generate multi-architecture Docker images (x86_64, ARM64) in a single afternoon with Antigravity.

    M
    Mario Ezquerro
    [Dev Log][Python] Create short videos from photos and clips with Gemini 3.7 Flash: ReelCraftai

    [Dev Log][Python] Create short videos from photos and clips with Gemini 3.7 Flash: ReelCraft

    Preface: It all started with a misunderstanding. I noticed a new page in the Gemini API...

    E
    Evan Lin
    Dart 3.13 Primary Constructors + BlocSignal: Boilerplate-Free Reactive Architectureflutter

    Dart 3.13 Primary Constructors + BlocSignal: Boilerplate-Free Reactive Architecture

    Discover how Dart 3.13 primary constructors, 'this' constructor bodies, and constructor shorthands transform BlocSignal into the cleanest state management architecture in Flutter.

    R
    Randal L. Schwartz
    Running Gemma 4 on EC2 G5g: Graviton2 AMD with NVIDIA GPUaws

    Running Gemma 4 on EC2 G5g: Graviton2 AMD with NVIDIA GPU

    A field report on serving Gemma 4 E2B under vLLM on AWS G5g — the only aarch64 + SM 7.5 hardware there is. No published build covers that combination, AWS quietly solves half of it, and the thing that actually blocks you is 64 KiB of shared memory.

    X
    xbill
    My (not so pretty) journey in techdiscuss

    My (not so pretty) journey in tech

    Ever since I joined the platform, I wanted to post about a topic I was really passionate about....

    I
    isha singh
    I Stopped Trusting AI Agents With Tools. So I Built a Gatekeeper.ai

    I Stopped Trusting AI Agents With Tools. So I Built a Gatekeeper.

    Update 08/15 0.2.0 Released github.com/deghosal-2026/agent-tooltrust · pip install agent-tooltrust...

    D
    Debashish Ghosal

    Stay up to date

    Get the latest CoPilot prompts, rules, and resources delivered to your inbox weekly.

    Neura Market LogoNeura Market

    Discover the best AI prompts, plugins, and resources for CoPilot and more.

    Content Types

    • Rules
    • Prompts
    • MCPs
    • Agents
    • Guides

    Platforms

    • ChatGPT Directory
    • Claude Directory
    • Gemini Directory
    • Cursor Directory
    • Grok Directory
    • Perplexity Directory
    • DeepSeek Directory
    • CoPilot Directory
    • Stable Diffusion Directory
    • Midjourney Directory
    • All Directories

    Resources

    • Blog
    • Documentation
    • Help Center
    • Marketplace

    Legal

    • Privacy Policy
    • Terms of Service

    © 2026 Neura Market. All rights reserved.

    |

    Not affiliated with any AI platform vendors.

    Neura Market

    Custom AI Systems & Services

    Our team of experienced AI builders will help build custom AI systems, workflows, and solutions.

    Request custom work

    Ready-made automations for this

    Workflows from the Neura Market marketplace related to this CoPilot resource

    • Automate Employee Data Tracking & Reminders for HR with JavaScriptn8n · $14.99 · Related topic
    • Learn JavaScript Data Processing with CodeNode: Filtering, Analysis, & Export Examplesn8n · $9.99 · Related topic
    • Learn JavaScript Coding with an Interactive RPG-Style Tutorial Gamen8n · $9.99 · Related topic
    • Deduplicate Data Records Using JavaScript Array Methodsn8n · $9.99 · Related topic
    Browse all workflows