Skip to content

meta(changelog): Update changelog for 11.5.0 - #25125

Merged
chargome merged 74 commits into
masterfrom
prepare-release/11.5.0
Oct 7, 2026
Merged

chargome merged 74 commits into
masterfrom
prepare-release/11.5.0

Conversation

@chargome

@chargome chargome commented Oct 7, 2026

Copy link
Copy Markdown
Member

No description provided.

github-actions Bot and others added 30 commits October 2, 2026 16:56
[Gitflow] Merge master into develop
…amework (#24598)

POC for running one framework e2e app on several server runtimes instead
of one app per runtime (Linear project P-JS-2537).
`react-router-8-framework` now runs its full Playwright suite on Bun,
Deno and Cloudflare (local workerd) as optional variants, next to the
Node job.

Each runtime inits its own SDK, the way a user of that runtime would:
Node `@sentry/react-router`, Bun `@sentry/bun`, Deno `@sentry/deno`
(with `--preload=@sentry/deno/import`) and Cloudflare
`@sentry/cloudflare`. `@sentry/react-router` then only provides the
framework wrappers, so values from its `init()` (`sdk.name`, the
`runtime` tag, the `/__manifest` filter) are Node-only, and the tests
branch on that. Using the runtime SDKs is what makes the Bun variant
work: `@sentry/node` creates no `http.server` span on Bun, `@sentry/bun`
does.

A variant declares its runtime with a `runtime` field instead of the
label. From it, both e2e jobs install Bun or Deno, the runner and CI set
`RUNTIME` for the build and the assert command (read with the new
`getRuntime()` from `@sentry-internal/test-utils`, and
`playwright.config.mjs` picks the start command from it), and the runner
copies the files named for that runtime over their base files in the
temporary copy of the app. So the Cloudflare build gets
`vite.cloudflare.config.ts` (`@cloudflare/vite-plugin` +
`sentryCloudflareVitePlugin`) and `entry.server.cloudflare.tsx`, while
Bun and Deno reuse the Node build. React Router has no option to pick a
server entry, and this way a variant needs no framework or bundler
config and no `build.yml` change. The Bun and Deno variants of `hono-4`
and `hono-4-legacy` set `runtime` too, because CI no longer reads the
runtime from the label. The convention is in the e2e README.

Other expected differences: Express is not instrumented under `bun run`
and there is no Express layer on workerd, so there the error transaction
stays the request path and the meta tag names the `http.server` span.
Deno is pinned to v2.9.0, because Deno 2.8 loses async context in socket
callbacks and drops `ioredis` spans.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…25017)

Remove static lifecycle pins from non-tracing integration suites so they
exercise the default span-streaming lifecycle. Session and Pino tests
now ignore span envelopes instead of transactions.

Part of #24141 (JS-3611): mechanical pin-removal portion

Co-authored-by: GPT-6 <codex@openai.com>
Exercise Bun request-body capture with default span streaming,
preserving the existing metadata, truncation, disabled-capture, and
handler-body assertions. The body is available on the streamed segment
as `http.request.body.data`, so this suite no longer needs a static
lifecycle pin.

Static transaction coverage remains in `elysia-bun-static`.

Fixes #24134

---------

Co-authored-by: GPT-6 <codex@openai.com>
…span streaming (#25020)

Move rejection, feature-flag, GrowthBook, and client-report coverage to
the default span-streaming lifecycle. Preserve existing assertions while
adapting transaction checks to streamed spans and allowing span/error
envelopes to arrive in either order.

Part of #24141 (JS-3611)

---------

Co-authored-by: GPT-6 <codex@openai.com>
Move AWS integration coverage to the default span-streaming lifecycle
and fold the streamed twin into the original suite. Preserve the
existing assertions and both SDK-version variants in ESM and CJS,
collecting spans across envelopes before asserting.

Part of #24141 (JS-3611).

Co-authored-by: GPT-6 <codex@openai.com>
…er-8-framework (#24599)

part of #24836

With the Cloudflare variant of `react-router-8-framework`, the separate
`react-router-8-cloudflare` app only added its MySQL test. This moves
the MySQL route and both tests into `react-router-8-framework` and
removes the old app, so one app covers React Router on Node, Bun, Deno
and Cloudflare.

The MySQL tests now run on every variant, not only on Cloudflare. The
Worker is wrapped by `sentryCloudflareVitePlugin` instead of a manual
`withSentry` call; other Cloudflare apps still cover manual
`withSentry`.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Uses `SENTRY_OP` from `@sentry/conventions/attributes` throughout SDK
instrumentation and tests. It is an exact replacement for `sentry.op`;
emitted values, attribute precedence, and serialization remain
unchanged.

Deprecates the existing core constant while preserving its public export
and SDK re-exports for backward compatibility.

Part of #24961 / [JS-3868](https://linear.app/getsentry/issue/JS-3868).

---------

Co-authored-by: GPT-6 <codex@openai.com>
…25033)

## What

Workers AI calls now become `evaluate` spans only when the model ID
starts with `typesafe/jev`, not when the input has `state` and
`questions`.

## Why

The input shape is a loose signal: any other model with those fields was
traced as an evaluation. Jev is an evaluation model, so its model ID is
exact, and other TypeSafe models stay unaffected. Follow-up to #24833.

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Ports the remaining `astro-5-cf-workers` E2E app to default span
streaming. `astro-7-static` retains the group's static lifecycle
coverage.

The server config is intentionally empty so Astro does not inject its
default Node SDK initialization. The Cloudflare wrapper already
initializes Sentry from Wrangler bindings, reinitializing during the
first page load dropped that request's streamed span.

Fixes #23809

---------

Co-authored-by: GPT-6 <codex@openai.com>
Run filesystem instrumentation tests with the default span-streaming
lifecycle. Preserve the existing path, error, and recording-option
assertions while adapting them to streamed span fields. Each test
asserts its request's span container directly.

Closes #24141 (JS-3611)

---------

Co-authored-by: GPT-6 <codex@openai.com>
Uses `SENTRY_ORIGIN` from `@sentry/conventions/attributes` in the
browser SDK, browser framework integrations, and their tests. It has the
same `sentry.origin` value; transmitted data and public exports are
unchanged.

Part of #24961 / [JS-3868](https://linear.app/getsentry/issue/JS-3868).

Co-authored-by: GPT-6 <codex@openai.com>
…24983)

Uses `SENTRY_ORIGIN` from `@sentry/conventions/attributes` in core,
browser-utils, OpenTelemetry tests, and Effect tracing/logging. It has
the same `sentry.origin` value; transmitted data and public exports are
unchanged.

Part of #24961 / [JS-3868](https://linear.app/getsentry/issue/JS-3868).

Co-authored-by: GPT-6 <codex@openai.com>
## What

Adds an e2e test to the eve app. The test makes an agent tool call a
TypeSafe Jev evaluation.

## Why

Make sure a Jev evaluation in an eve tool records a `gen_ai.evaluate`
span under the tool span.

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Uses `SENTRY_ORIGIN` from `@sentry/conventions/attributes` in full-stack
framework integrations and their tests. It has the same `sentry.origin`
value; transmitted data and public exports are unchanged. Nuxt’s private
database-origin constant is renamed to avoid an import collision; its
value remains `auto.db.nuxt`.

Part of #24961 / [JS-3868](https://linear.app/getsentry/issue/JS-3868).

Co-authored-by: GPT-6 <codex@openai.com>
Uses `SENTRY_ORIGIN` from `@sentry/conventions/attributes` in server
instrumentation, runtimes, and their tests. It has the same
`sentry.origin` value; transmitted data and public exports are
unchanged.

Part of #24961 / [JS-3868](https://linear.app/getsentry/issue/JS-3868).

Co-authored-by: GPT-6 <codex@openai.com>
…mming (#25040)

Fix screenshot annotations starting at the wrong position when a drag
begins inside an existing box, and prevent the background from getting
darker while dragging. Mouse-down now uses image-relative coordinates
consistently, and highlight shadows no longer leak into the next canvas
repaint.

reported here:
https://sentry.slack.com/archives/CDXAKMGTU/p1790972462069039

Before/after from a local reproduction with generated sample content.
Both captures show the same drag with the mouse held down; red markers
indicate its start and cursor positions.

| Before | After |
| --- | --- |
|
![Before](https://github.com/user-attachments/assets/6db1d723-f00b-49ba-bb4b-f82719cc2d69)
|
![After](https://github.com/user-attachments/assets/dabac060-1b21-45e8-83c4-5429fa41dbd6)
|

---------

Co-authored-by: OpenAI Codex <codex@openai.com>
Marks `SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN` as deprecated in favor of
`SENTRY_ORIGIN` from `@sentry/conventions/attributes`. This PR finalizes
the replacement of all SDK constants that are available in the
conventions package.

Fixes #24961 / [JS-3868](https://linear.app/getsentry/issue/JS-3868).

Co-authored-by: GPT-6 <codex@openai.com>
Adds `code.file.path` to `cache.put` spans, so `use cache` spans show
which function they belong to.

The cache key contains the function id. Next.js' server-reference
manifest maps it to the source file. Keys come in two forms:

- JSON: `["buildId","c0a941ad…",[args]]` (start with `[`)
- multipart, when args don't serialize to JSON (`params`, `children`):
`1:069:["buildId","c0a941ad…",[…]]1:1c:{"id":"123"}` (length-prefixed
fields)


Logged real-world data to use this in the unit tests (from 16.3 and
canary version).

Linear:
https://linear.app/getsentry/issue/JSSDK-31/add-cache-source-file-to-trace-back-where-the-cache-was-created
…n Firefox (#25024)

Replay calls our `setTimeout` from `@sentry/browser-utils`. When
`window.setTimeout` is wrapped (by default it is, by our own
`browserApiErrors` integration), that `setTimeout` comes from a sandbox
iframe that is removed right away. In rare cases Firefox throws
`NS_ERROR_NOT_INITIALIZED` when it is called, which shows up as an
unhandled rejection from Replay's `afterSendEvent` handler. This catches
the error, falls back to `window.setTimeout` and caches it.

---------

Co-authored-by: Sergiy Dybskiy <sergical@users.noreply.github.com>
Co-authored-by: sentry[bot] <39604003+sentry[bot]@users.noreply.github.com>
Co-authored-by: Lukas Stracke <lukas.stracke@sentry.io>
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…24985)

Next.js removes the `basePath` from `req.url` before running Pages
Router data fetchers and API routes. So errors captured there reported a
`request.url` without it, for example `http://localhost:3000/foo/bar`
instead of `http://localhost:3000/base/foo/bar`.

Next keeps the URL as it was originally requested in its internal
request meta (`initURL`), set before the `basePath` is removed. We now
take the path and query from there. The origin still comes from the
request headers, because Next builds the absolute `initURL` from its own
hostname and port, which can differ from the public host behind a proxy.
API routes were affected the same way, so they're covered too.

Fixes #24975

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
follow up from
#23760 (comment)

Remove the unconditional warning when `beforeSendSpan` returns `null`,
saving ~90B (compressed) / ~200B (uncompressed).

The type already disallows returning null since v9. Keeps the runtime
fallback to the original span for JavaScript callers, with one
regression test covering the shared behavior.

Co-authored-by: GPT-6 <codex@openai.com>
Port the AWS serverless GraphQL integration test to default span
streaming. Preserve startup and operation span checks, including the
operation name, successful status, and instrumentation origin.

Part of #24139

---------

Co-authored-by: GPT-6 <codex@openai.com>
…gy (#24995)

`withSentry`, Durable Objects, Workflows and `WorkerEntrypoint` install
the AsyncLocalStorage async context strategy. When an OpenTelemetry
strategy is already installed, the new strategy reuses its
`AsyncLocalStorage` but stores Sentry scopes in it. The OpenTelemetry
context manager then reads a scope store as a context, and every later
request fails with `context.getValue is not a function` (#24603). They
now keep an installed OpenTelemetry strategy.

This is needed for `@sentry/nextjs/cloudflare`, which installs the
OpenTelemetry strategy before it calls `withSentry`, and for apps whose
`register()` runs before the Worker entry. The check uses
`withActiveSpan`, which only the OpenTelemetry strategy has, so no new
marker is needed. The Pages plugin is unchanged.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Reuse the existing `isObjectLike` helper for repeated non-null object
guards across SDK packages. It checks the same runtime condition and
narrows unknown values, allowing redundant type assertions to be removed
without changing behavior.

Co-authored-by: OpenAI Codex <codex@openai.com>
…25061)

The public types of `@sentry/sveltekit` include
`consoleLoggingIntegration` from the Node entry. But the worker entry,
which Cloudflare selects through the `worker` and `workerd` conditions,
did not re-export it from `@sentry/cloudflare`. So
`Sentry.consoleLoggingIntegration()` was `undefined` on Workers.

This adds only that one export. Other Node-typed exports are also
missing from the worker entry. We will handle them with a dedicated
Cloudflare entry point, which can also fix the types (#24841).

Fixes #24965

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Embroider published new patch versions of vite, macros, core and compat
today with almost no files in the tarballs, which broke every ember e2e
app, fixed by overriding just those versions back to the previous ones
in the test apps.

The overrides are scoped to the broken versions, so they stop applying
once a fixed release is out and can be removed then.
We were on web-vitals 6.1.1, so I bumped it to the latest 6.2.3 to pick
up the upstream fixes.

**Changelog**

- Fixes an INP clean-up memory leak and caps pending LoAFs to avoid
another leak
([#799](GoogleChrome/web-vitals#799),
[#796](GoogleChrome/web-vitals#796))
- Fixes negative `resourceLoadDuration` in LCP attribution and negative
`inputDelay` in INP attribution
([#803](GoogleChrome/web-vitals#803),
[#789](GoogleChrome/web-vitals#789))
- Stops a spurious CLS report of 0 after a bfcache restore
([#786](GoogleChrome/web-vitals#786))
- Guards `supportedEntryTypes` for older browsers
([#787](GoogleChrome/web-vitals#787))
… on gen_ai spans (#24721)

v10 got `vercel.ai.telemetry.metadata.<key>` attributes from the AI
SDK's own OTel spans. In v11, `ai` 4 to 6 go through the orchestrion
subscriber, which never read `metadata`, so v11 dropped it.

The orchestrion subscriber now passes the metadata to the channel
subscriber, which sets it as span attributes when each span starts. The
`invoke_agent`, `generate_content` and `embeddings` spans get the
attributes, and `execute_tool` spans don't. This matches the AI SDK,
which leaves metadata off its `ai.toolCall` spans.

Values are cast to string, as discussed in the linked sentry-conventions
PR. If this causes a problem we can revisit, but all extant examples
found in the wild are strings already, so it is likely safe, and
extremely cheap.

fixes JS-3800
fixes #24720
Re: #24706
Re: getsentry/sentry-conventions#662

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
)

On Vercel, a function can be suspended as soon as it sends the response.
Telemetry that is still buffered (spans, logs, metrics, errors) then
arrives late or never.

When a response finishes, `@sentry/node` now uses `waitUntil` to keep
the function alive. It waits until the response closes and the request's
root span ends (2 s max), then flushes. It works with or without
tracing.

Some frameworks end the root span shortly after the response closes, so
the flush waits for it.

Tested with unit tests and an integration test that fails without the
change, and confirmed on a Vercel deployment.

Closes #24909
Refs #23087

---------

Co-authored-by: Claude <claude@anthropic.com>
javascript-sdk-gitflow Bot and others added 11 commits October 6, 2026 17:26
This PR adds the external contributor to the CHANGELOG.md file, so that
they are credited for their contribution. See #25025

Co-authored-by: JPeer264 <10677263+JPeer264@users.noreply.github.com>
…AI conversation option (#24979)

The Vercel AI integration filled `gen_ai.conversation.id` with
`providerMetadata.openai.responseId`. That is the id of the response
that just came back, so every call got a different value under a
grouping attribute and showed up as its own one-span conversation. The
same value is already on `gen_ai.response.id`. The mapping came in with
#16992 and #19903 later had to guard it from overwriting user-set ids.

The id now comes from `providerOptions.openai.conversation` (or
`azure`), the Conversations API `conv_` id, which is the same on every
turn. Child model-call and tool spans inherit it from the active
operation span. `Sentry.setConversationId()` still wins, since
`conversationIdIntegration` writes the scope value on `spanStart` after
these start attributes. The v6 adapter forwards `providerOptions` so
`ai` 4 to 6 behave the same.

Not in this PR: reading the id from `runtimeContext` /
`experimental_telemetry.metadata` goes with #24706 once #24721 lands.

Part of #24832

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
…#24831)

The LangChain integration only set `gen_ai.conversation.id` when the
user called `Sentry.setConversationId()` themselves. LangGraph read
`configurable.thread_id`, but stamped it on its own `invoke_agent` span
only, so the chat and tool child spans went out without it.

Child runs inherit their parent's metadata, so this PR reads the
conversation id from run metadata and sets the attribute on the chat,
chain and tool spans. On `@langchain/core` 0.1.20 to 1.1.39,
`ensureConfig` copies every primitive `config.configurable` entry into
that metadata, so an id passed to `invoke()` is already there.
`@langchain/core` 1.1.40 stopped doing that for any handler except
LangSmith's tracer. So where we inject our handler, in the chat-model
hook and the LangGraph `invoke` proxy, we copy the three keys below from
`configurable` into `metadata` ourselves. Metadata the user set takes
precedence.

Keys read, in order:

- `thread_id`, the LangGraph checkpointer key and one of the two keys
LangSmith groups threads by
- `session_id`, the other LangSmith key
- `sessionId`, what `RunnableWithMessageHistory` requires in JS

An id set on the scope via `Sentry.setConversationId()` still wins.
`conversationIdIntegration` applies it on `spanStart`, after the initial
attributes, so an explicit user id overwrites the derived one. The
integration test covers this.

LangGraph's `invoke_agent` span and the tool spans `createReactAgent`
creates now use the same helper. So they read the same keys, accept
numeric ids, and let an id from `Sentry.setConversationId()` win over
`thread_id`. Before, `thread_id` overwrote the scope id on the
`invoke_agent` span only, and the tool spans never picked up
`thread_id`.

One gap remains on `@langchain/core` >= 1.1.40. If you pass
`createLangChainCallbackHandler()` yourself to a chain outside
LangGraph, the chain and tool spans get no id from `configurable`,
because the handler never sees it. The chat spans still get it. Closing
that would mean hooking more than chat models, so it is left for a
follow-up.





**Bun.** The new suite failed on the Bun runner because `@sentry/bun`
builds its own default integration list and never registered
`conversationIdIntegration`, so `Sentry.setConversationId()` was a no-op
there. The second commit adds it, in the same position Node uses.

Part of #24832.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
The release API rejects a release without a project, and the project
given to the `sentry` SDK does not reach `release.create`. Since the
move to that SDK (#23398), `sentry-upload-sourcemaps` failed with `400
Bad Request` on every run. The unit test mocked the SDK, so it did not
catch it. Reproduced against a real org.

Both upload scripts take the project from `--project`, then
`SENTRY_PROJECT`, and fail with a clear message when neither is set.
`@sentry/bundler-plugins` already did this. The React Router Vite plugin
has the same bug, fixed separately.

Fixes #24989

---------

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
The release API rejects a release without a project, and the project
given to the `sentry` SDK does not reach `release.create`. Since the
move to that SDK (#23398), the Vite plugin logged `[Sentry] Could not
create release` on every build; the upload itself still ran, so builds
succeeded without a release. The unit test mocked the SDK, so it did not
catch it.

The plugin now passes the project it already has, as
`@sentry/bundler-plugins` does. Same bug in the Remix upload scripts,
fixed in #25079.

Refs #24989

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
Cloudflare documents Clef (`@cf/cloudflare/clef`) as a drop-in for Jev
with the same `state` + `questions` request shape, so it already goes
through the `evaluate` path from #24833. Only Jev had tests, so this
adds a Clef integration test and a real-Worker E2E test.

The integration mock returns the documented Clef response, which has no
`{ state, result }` wrapper (the Jev binding response has one). That
makes it cover the unwrapped branch of the evaluate response handling,
which the Jev test does not reach. The E2E test calls the real model, so
it is the one that confirms what the binding actually returns. The docs
do not give a `model` value for the response, so it only asserts that it
contains `clef`.

Fixes #25011

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…25088)

Next.js 16.4 canary drops the `authInterrupts` flag, so
`forbidden()`/`unauthorized()` throws
(`NEXT_HTTP_ERROR_FALLBACK;403`/`;401`) now need to be treated as
control flow like `notFound()`.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…25117)

Next.js 16.4 Turbopack now lists route handler `use cache` functions in
the server-reference manifest, so `code.file.path` is set on `cache.put`
spans for both bundlers.

This drops the webpack-only expectation in both cacheComponents E2E
apps, which started failing once CI resolved `next@^16` to 16.4.0.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…#25118)

`@opennextjs/cloudflare` throws on the new `preview-props.json` manifest
that Next.js 16.4 loads, so every request in the `(latest)` variant
returns a 500
(opennextjs/opennextjs-cloudflare#1355).

This pins the variant to 16.3 until the upstream fix
(opennextjs/opennextjs-cloudflare#1356) is
released, and we should switch it back to `next@latest` then.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Cached-token usage was inconsistent across AI integrations: Anthropic
reported only uncached input tokens, some integrations dropped cache
breakdowns, and LangChain could overwrite complete usage with counters
from the final stream chunk. This produced incomplete totals and could
leave cache counts greater than the reported input count, breaking
downstream pricing.

This PR treats input and output counts as inclusive totals. Cache reads
and writes are subsets of input, and reasoning tokens are a subset of
output. Provider-specific normalization happens before setting those
attributes, so the breakdowns are never added to an already-inclusive
total.

- **Anthropic:** Include cache reads and writes in input usage and emit
both breakdown attributes for regular and streaming responses.
- **OpenAI:** Preserve cache details from Chat Completions and Responses
usage without increasing their existing totals.
- **Google GenAI:** Preserve cached-input usage and include thinking
tokens in output, with reasoning reported separately.
- **LangChain:** Prefer normalized message usage over generic
`tokenUsage`, which can contain only the final stream chunk’s counters.
Normalize raw Anthropic usage as a fallback and count shared candidate
usage once per prompt.
- **LangGraph:** Aggregate cache breakdowns alongside token totals for
newly generated messages, excluding conversation history.

Regression coverage includes competing usage sources, repeated streaming
events, missing and zero cache counts, batched prompts, and shared
candidate usage.

Fixes #25069

---------

Co-authored-by: GPT-6 <codex@openai.com>
Co-authored-by: Andrei <168741329+andreiborza@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@chargome
chargome marked this pull request as ready for review October 7, 2026 09:40
@chargome
chargome requested review from a team as code owners October 7, 2026 09:40
@chargome
chargome requested review from isaacs, msonnb, mydea and nicohrubec and removed request for a team October 7, 2026 09:40
@github-actions

github-actions Bot commented Oct 7, 2026

Copy link
Copy Markdown
Contributor

size-limit report 📦

⚠️ Warning: Base artifact is not the latest one, because the latest workflow run is not done yet. This may lead to incorrect results. Try to re-run all tests to get up to date results.

Path Size % Change Change
@sentry/browser 29.6 kB +0.28% +82 B 🔺
@sentry/browser - with treeshaking flags 27.75 kB +0.26% +71 B 🔺
@sentry/browser - with treeshaking flags tracing without tracing 27.65 kB +0.28% +76 B 🔺
@sentry/browser (incl. Tracing) 51.52 kB +0.14% +68 B 🔺
@sentry/browser (incl. Tracing + Span Streaming) 51.52 kB +0.12% +59 B 🔺
@sentry/browser (incl. Tracing, Profiling) 54.5 kB +0.08% +42 B 🔺
@sentry/browser (incl. Tracing, Replay) 91.23 kB +0.21% +185 B 🔺
@sentry/browser (incl. Tracing, Replay) - with treeshaking flags 80.18 kB +0.2% +156 B 🔺
@sentry/browser (incl. Tracing, Replay with Canvas) 95.93 kB +0.2% +187 B 🔺
@sentry/browser (incl. Tracing, Replay, Feedback) 108.89 kB +0.17% +184 B 🔺
@sentry/browser (incl. Feedback) 47.12 kB +0.17% +76 B 🔺
@sentry/browser (incl. sendFeedback) 34.65 kB +0.24% +80 B 🔺
@sentry/browser (incl. FeedbackAsync) 39.76 kB +0.19% +73 B 🔺
@sentry/browser (incl. Metrics) 30.61 kB +0.24% +71 B 🔺
@sentry/browser (incl. Logs) 30.89 kB +0.21% +62 B 🔺
@sentry/browser (incl. Metrics & Logs) 31.55 kB +0.23% +70 B 🔺
@sentry/react 31.43 kB +0.22% +69 B 🔺
@sentry/react (incl. Tracing) 53.84 kB +0.06% +32 B 🔺
@sentry/vue 37.55 kB +0.11% +38 B 🔺
@sentry/vue (incl. Tracing) 54.4 kB +0.13% +66 B 🔺
@sentry/svelte 29.63 kB +0.27% +77 B 🔺
@sentry/remix (Remix 3 client bundle) 56.54 kB +1.37% +760 B 🔺
CDN Bundle 31.33 kB +0.35% +109 B 🔺
CDN Bundle (incl. Tracing) 52.07 kB +0.17% +85 B 🔺
CDN Bundle (incl. Logs, Metrics) 33.56 kB +0.3% +100 B 🔺
CDN Bundle (incl. Tracing, Logs, Metrics) 54.03 kB +0.21% +113 B 🔺
CDN Bundle (incl. Replay, Logs, Metrics) 74.38 kB +0.24% +174 B 🔺
CDN Bundle (incl. Tracing, Replay) 89.74 kB +0.21% +181 B 🔺
CDN Bundle (incl. Tracing, Replay, Logs, Metrics) 91.69 kB +0.18% +162 B 🔺
CDN Bundle (incl. Tracing, Replay, Feedback) 95.9 kB +0.19% +180 B 🔺
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics) 97.87 kB +0.17% +157 B 🔺
CDN Bundle - uncompressed 92.46 kB +0.35% +318 B 🔺
CDN Bundle (incl. Tracing) - uncompressed 154.77 kB +0.18% +277 B 🔺
CDN Bundle (incl. Logs, Metrics) - uncompressed 99.04 kB +0.33% +324 B 🔺
CDN Bundle (incl. Tracing, Logs, Metrics) - uncompressed 160.72 kB +0.18% +277 B 🔺
CDN Bundle (incl. Replay, Logs, Metrics) - uncompressed 228.98 kB +0.31% +692 B 🔺
CDN Bundle (incl. Tracing, Replay) - uncompressed 274.89 kB +0.25% +667 B 🔺
CDN Bundle (incl. Tracing, Replay, Logs, Metrics) - uncompressed 280.83 kB +0.24% +667 B 🔺
CDN Bundle (incl. Tracing, Replay, Feedback) - uncompressed 288.59 kB +0.24% +667 B 🔺
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics) - uncompressed 294.52 kB +0.23% +667 B 🔺
@sentry/nextjs (client) 56.19 kB -0.23% -128 B 🔽
@sentry/sveltekit (client) 51.9 kB +0.07% +34 B 🔺
@sentry/core/server 40.65 kB +0.15% +59 B 🔺
@sentry/core/browser 13.51 kB -0.83% -112 B 🔽
@sentry/node 145.57 kB +0.57% +820 B 🔺
@sentry/node/import (ESM hook with diagnostics-channel injection) 83.22 kB - -
@sentry/node - without tracing 93.46 kB +0.16% +146 B 🔺
@sentry/node - without channel injection 123.73 kB +0.63% +771 B 🔺
@sentry/aws-serverless 101.69 kB +0.11% +109 B 🔺
@sentry/cloudflare (withSentry) - minified 209.03 kB +0.2% +417 B 🔺
@sentry/cloudflare (withSentry) 517.8 kB +0.08% +391 B 🔺

View base workflow run

Comment on lines +28 to +30
process.on('SIGTERM', async () => {
// We have 500ms for processing here, so we try to make sure to have enough time to send the events
await client.flush(200);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Bug: Calling init() multiple times registers duplicate SIGTERM and diagnostic channel handlers in setupVercelKeepAlive, causing resource leaks and redundant processing on each server response.
Severity: MEDIUM

Suggested Fix

Add a guard within setupVercelKeepAlive to ensure its logic only executes once per process. A simple boolean flag can be used to track if the setup has already been performed. This will prevent the accumulation of handlers on subsequent calls to init().

Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent. Verify if this is a real issue. If it is, propose a fix; if not, explain why it's
not valid.

Location: packages/node/src/sdk/vercel.ts#L28-L30

Potential issue: The `setupVercelKeepAlive` function is called unconditionally every
time `init()` is invoked. This function registers a `SIGTERM` handler and subscribes to
the `HTTP_ON_SERVER_RESPONSE_FINISH` diagnostics channel. Because there is no guard to
prevent re-registration, multiple calls to `init()` will cause an accumulation of these
handlers. This results in redundant `client.flush()` operations on process termination
and duplicate processing for each HTTP response, leading to a resource leak and
potential performance degradation, especially in scenarios with hot module replacement
or complex initialization paths.

Did we get this right? 👍 / 👎 to inform future reviews.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

will check if this is actually an issue

@chargome
chargome merged commit a8f5eb0 into master Oct 7, 2026
348 checks passed
@chargome
chargome deleted the prepare-release/11.5.0 branch October 7, 2026 09:50
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.