---
title: "Interactive v11 Migration Guide"
description: "Migrate from Sentry JavaScript SDK 10.x to 11.x with an interactive checklist for your platform."
url: https://docs.sentry.io/platforms/javascript/guides/vue/migration/v10-to-v11/interactive/
---

# Interactive v11 Migration Guide | Sentry for Vue

Version 11 of the Sentry JavaScript SDK focuses on better OpenTelemetry interoperability, more flexible instrumentation, and better out-of-the-box defaults. It raises the minimum versions of Node.js, TypeScript, and several frameworks.

We recommend upgrading to the most recent 10.x release first, because most of what v11 removes is already deprecated there.

This checklist shows all migration steps for your selected platform. Some steps only apply to specific integrations or configuration options. For the full write-up of every change, see the [migration guide](https://docs.sentry.io/platforms/javascript/guides/vue/migration/v10-to-v11.md).

TypeScript and other tooling won't catch all of these changes. Read through the steps below before upgrading, rather than upgrading and fixing what breaks.

## [Your Migration Steps](https://docs.sentry.io/platforms/javascript/guides/vue/migration/v10-to-v11/interactive.md#your-migration-steps)

## Check prerequisites

4 left

Runtime, language and framework versions you need before upgrading.

### Self-hosted Sentry 26.4.2 is the new minimum

Action required

Version 11 of the SDK requires Sentry self-hosted 26.4.2 or higher. Lower versions may continue to work, but are not supported. We recommend that you update self-hosted Sentry to the latest version.

### Node.js 20.19.0 is the new minimum

Action required

Node.js 18 is no longer supported. The minimum is **20.19.0**, and Node.js 22 needs **22.12** or higher while Node.js 23 needs **23.2** or higher (`>=20.19.0 <22.0.0 || >=22.12.0 <23.0.0 || >=23.2.0`).

Move to a supported version everywhere the SDK is installed or your app is built: Dockerfiles, CI images, `engines`, `.nvmrc`, and serverless runtime settings.

The same supported Node.js range applies if you use Node.js to install dependencies or build a browser project. Loading the SDK directly in a browser from a CDN does not require Node.js.

### Safari 14 support was dropped

Behavior change

Safari 14 is no longer supported. It lacks `performance.timeOrigin` and full `visibilitychange` support, which the web vitals instrumentation had to work around. The SDK still requires ES2020, so the rest of the matrix is unchanged:

* Chrome 80
* Edge 80
* Safari 15, iOS Safari 15
* Firefox 74
* Opera 67
* Samsung Internet 13.0

The same supported Node.js range applies if you use Node.js to install dependencies or build a browser project. Loading the SDK directly in a browser from a CDN does not require Node.js.

### TypeScript 5.0.4 is the new minimum

Action required

The minimum required TypeScript version is **5.0.4**. The SDK no longer ships down-leveled types. Older TypeScript versions *may* continue to work, but no guarantees apply.

## Update packages

3 left

Installs, removals and moved entry points.

### \`@sentry/types\` is no longer published

Action required

`@sentry/types` is no longer published. Import all types from `@sentry/core`. The package has only re-exported from `@sentry/core` since v8.

### Browser and server exports moved to \`@sentry/core\` subpaths

Action required

`@sentry/core` exports only isomorphic code now. Browser-only exports live on `@sentry/core/browser` and server-only ones on `@sentry/core/server`, which keeps server code out of browser bundles. This only affects imports straight from `@sentry/core`, since the platform SDKs re-export as before. TypeScript reports it as `has no exported member`.

```js
// Before
import { loadModule, trpcMiddleware } from "@sentry/core";
import type { BrowserClientReplayOptions } from "@sentry/core";

// After
import { loadModule, trpcMiddleware } from "@sentry/core/server";
import type { BrowserClientReplayOptions } from "@sentry/core/browser";
```

### Metrics moved out of the base CDN bundle

Action required

Metrics moved out of the base CDN bundle. They ship only in the `*.logs.metrics` bundles now. On the other bundles, `Sentry.metrics.*` is a no-op that warns in debug builds.

## Make required code changes

20 left

Options, APIs and config that changed and need your attention.

### \`sendDefaultPii\` is replaced by \`dataCollection\`

Action required

`sendDefaultPii` is replaced by `dataCollection`, which controls each category of collected data separately. Our blog post [The Data Collection Control Panel](https://blog.sentry.io/datacollection-control-panel/) covers the thinking behind it.

This is a behavior change, not a rename. In v10, an unset `sendDefaultPii` was restrictive. In v11, an unset `dataCollection` collects everything by default.

| Category              | v10 default (`sendDefaultPii` off) | v11 default          |
| --------------------- | ---------------------------------- | -------------------- |
| `userInfo`            | `false`                            | `true`               |
| `cookies`             | not collected                      | `true`               |
| `httpHeaders`         | request + response, PII scrubbed   | request + response   |
| `httpBodies`          | not collected (size only)          | all request/response |
| `urlQueryParams`      | `true`                             | `true`               |
| `genAI`               | inputs + outputs not collected     | inputs + outputs     |
| `databaseQueryData`   | `false`                            | `true`               |
| `stackFrameVariables` | `true`                             | `true`               |
| `frameContextLines`   | `7`                                | `5`                  |

If you set `sendDefaultPii: true`, remove it. The v11 default matches that behavior.

If you relied on the v10 default, set the baseline explicitly.

Sentry scrubs values whose key looks sensitive (e.g. `auth`, `token`, `secret`, `password`). The match runs on the key name, so treat it as best effort: a credential in a field that isn't named like one still reaches Sentry. Review your [data scrubbing](https://docs.sentry.io/platforms/javascript/guides/vue/data-management/sensitive-data.md) config for the categories v11 collects now, especially request and response bodies.

Keeping the v10 collection defaults

```js
Sentry.init({
  dataCollection: {
    userInfo: false,
    cookies: false,
    httpHeaders: {
      request: { deny: ["forwarded", "-ip", "remote-", "via", "-user"] },
      response: { deny: ["forwarded", "-ip", "remote-", "via", "-user"] },
    },
    httpBodies: [],
    urlQueryParams: { deny: ["forwarded", "-ip", "remote-", "via", "-user"] },
    genAI: { inputs: false, outputs: false },
    databaseQueryData: false,
    graphQL: { document: false, variables: false },
  },
});
```

The `cookies`, `urlQueryParams`, and `httpHeaders` fields also accept `true`, `false`, `{ allow: string[] }`, or `{ deny: string[] }`.

See the [`dataCollection` option](https://docs.sentry.io/platforms/javascript/guides/vue/configuration/options.md#dataCollection) for the full list of categories.

### Span streaming is now the default

Behavior change

Tracing moves to span streaming in v11. Instead of holding a trace in memory and sending one transaction when the root span ends, the SDK sends spans in small batches as they finish. Transactions no longer exist: what used to be one transaction event is a service span with its child spans.

That changes how spans are sent, named, and filtered. Most of it isn't caught by TypeScript, so check your filters, dashboards, and alerts.

Spans are no longer capped at 1000 per transaction, and individual payload limits are higher. See [stream mode](https://docs.sentry.io/platforms/javascript/guides/vue/tracing/streamed-spans.md) for how it works.

Because no transaction events are produced, `beforeSendTransaction` and `ignoreTransactions` no longer do anything, and `beforeSendSpan` [receives a different payload](https://docs.sentry.io/platforms/javascript/guides/vue/migration/v10-to-v11/interactive.md#before-send-span-format).

### Scope tags and extra no longer apply to spans

Action required

Streamed spans only carry attributes, so scope `tags` and `extra` no longer reach any span, including the service span that replaced the transaction. They still apply to errors, so you don't have to remove them. In transaction mode (`traceLifecycle: 'static'`) they keep landing on the transaction as before.

Set attributes for everything that should be searchable on spans, which also applies them to logs and metrics:

```js
// Before: applied to the transaction
Sentry.setTag("order_id", order.id);
Sentry.setTags({ user_tier: user.tier });

// After: applied to spans, logs, and metrics
Sentry.setAttribute("order_id", order.id);
Sentry.setAttributes({ user_tier: user.tier });
```

Attributes accept strings, numbers, booleans, and arrays of those, so numbers and booleans no longer have to be stringified. Like tags, they can be set on a specific scope:

```js
// Applied to all spans, logs, and metrics of the application
Sentry.getGlobalScope().setAttributes({ "app.version": "2.1.0" });

// Applied to a single operation
Sentry.withScope((scope) => {
  scope.setAttribute("checkout.step", "payment");
});
```

### \`beforeSendSpan\` receives the streamed span format

Action required

`beforeSendSpan` now runs as each span finishes and receives a `StreamedSpanJSON` object. Its fields were renamed:

| Before (`SpanJSON`) | After (`StreamedSpanJSON`)     |
| ------------------- | ------------------------------ |
| `description`       | `name`                         |
| `data`              | `attributes`                   |
| `op`                | `attributes['sentry.op']`      |
| `timestamp`         | `end_timestamp`                |
| `status` (`string`) | `status` (`'ok'` or `'error'`) |

```js
// Before
Sentry.init({
  beforeSendSpan: (span) => {
    if (span.op === "db.query") {
      span.description = scrub(span.description);
      span.data["db.statement"] = scrub(span.data["db.statement"]);
    }
    return span;
  },
});

// After
Sentry.init({
  beforeSendSpan: (span) => {
    if (span.attributes["sentry.op"] === "db.query") {
      span.name = scrub(span.name);
      span.attributes["db.query.text"] = scrub(
        span.attributes["db.query.text"]
      );
    }
    return span;
  },
});
```

The `status` field of that payload is always set, and holds only `'ok'` or `'error'`. The finer-grained statuses of v10 (`internal_error`, `not_found`, and the rest) all map to `'error'`, with the original value kept on the span's `sentry.status.message` attribute.

If you used `withStreamedSpan()`, [remove the wrapper](https://docs.sentry.io/platforms/javascript/guides/vue/migration/v10-to-v11/interactive.md#with-streamed-span-noop).

A callback that doesn't match your `traceLifecycle` is never invoked: an unwrapped one is ignored in transaction mode, a wrapped one in stream mode. In transaction mode, wrap it with `Sentry.withStaticSpan()` and it keeps receiving the old `SpanJSON`. Turn on debug logging to see a warning about the mismatch.

### \`beforeSendTransaction\` no longer runs

Action required

Move data changes to `beforeSendSpan` and guard on `is_segment` to target the service span, which is what used to be the transaction. Use `ignoreSpans` to drop spans: `beforeSendSpan` can only change spans, not drop them.

```js
// Before
Sentry.init({
  ignoreTransactions: ["GET /health"],
  beforeSendTransaction: (event) => {
    event.transaction = scrubIds(event.transaction);
    return event;
  },
});

// After
Sentry.init({
  ignoreSpans: ["GET /health"],
  beforeSendSpan: (span) => {
    if (span.is_segment) {
      span.name = scrubIds(span.name);
    }
    return span;
  },
});
```

Scope `tags` and `extra` [aren't carried over to streamed spans](https://docs.sentry.io/platforms/javascript/guides/vue/migration/v10-to-v11/interactive.md#scope-attributes) either.

### \`ignoreTransactions\` is replaced by \`ignoreSpans\`

Action required

`ignoreTransactions` no longer does anything in stream mode because no transaction events are produced. Use `ignoreSpans` to drop spans.

Ignoring a service span drops its child spans with it, which is the same result as dropping a transaction. Because `ignoreSpans` applies to every span, narrow the filter with the object form so that child spans with the same name are kept:

```js
Sentry.init({
  ignoreSpans: [
    { name: "GET /health", attributes: { "sentry.op": "http.server" } },
  ],
});
```

### \`spanToJSON\` returns the streamed span format

Action required

`Sentry.spanToJSON()` now returns a `StreamedSpanJSON` object, the same shape `beforeSendSpan` receives. The `spanToStreamedSpanJSON` helper was removed, so replace calls to it with `spanToJSON`.

### Opting out of span streaming

FYI

Set `traceLifecycle: 'static'` to keep the previous model. In Node.js, Bun, Vercel Edge, and Cloudflare you can set the `SENTRY_TRACE_LIFECYCLE=static` environment variable instead.

```js
Sentry.init({
  traceLifecycle: "static",

  // `beforeSendSpan` must be wrapped with `Sentry.withStaticSpan`
  beforeSendSpan: Sentry.withStaticSpan((span) => {
    span.description = scrub(span.description);
    return span;
  }),
});
```

In transaction mode, `spanToStaticSpanJSON` returns the static `SpanJSON` format.

Transaction mode only exists for backwards compatibility and will be removed in a future major version. Treat it as a temporary measure.

### Span names are low cardinality

Behavior change

In stream mode, span names follow the [Sentry span name conventions](https://getsentry.github.io/sentry-conventions/names/). URLs, route parameters, and other client-supplied values are no longer part of the name:

| Span op                  | Before                                  | After                                    |
| ------------------------ | --------------------------------------- | ---------------------------------------- |
| `http.client`            | `GET https://api.example.com/users/123` | `GET api.example.com`                    |
| `http.server`            | `GET /users/123`                        | `GET /users/:id`, or `GET`               |
| `pageload`, `navigation` | `/users/123`                            | `/users/:id`, or `Pageload`              |
| `resource.*`             | `/assets/app.js`                        | `cdn.example.com`, or `Resource`         |
| `graphql`                | `query GetUser`                         | `GraphQL query`                          |
| `queue.*`                | `my-queue process`, `poll my-topic`     | `process my-queue`, `receive my-topic`   |
| `db.query`               | `SELECT * FROM "User" WHERE "id" = $1`  | `SELECT "User"`, or `Database operation` |

`http.server` names are unchanged when the SDK resolves a route, and fall back to the method alone when it can't. `pageload` and `navigation` fall back to `Pageload` and `Navigation`.

Database spans work the same way: a statement that touches no table (`SELECT NOW()`) summarizes to the bare operation (`SELECT`), and without a statement to summarize the name falls back to the database namespace, then to `Database operation`.

Whatever the name no longer carries stays on an attribute, in both trace lifecycles: `url.full` and `url.domain`, `graphql.operation.name` and the new `graphql.processing.type`, `db.query.text`, and so on.

Full list of span name changes

| Span op                     | Before                                                                              | After                                                                                                                                     |
| --------------------------- | ----------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
| `pageload`, `navigation`    | The route, or the raw URL path (`/users/123`)                                       | The route, or `Pageload` and `Navigation`                                                                                                 |
| `http.server`               | The method and route, or the raw URL path (`GET /users/123`)                        | `GET /users/:id`, or the method alone (`GET`)                                                                                             |
| `http.client*`              | The method and sanitized URL (`GET https://api.example.com/users/123`)              | The method and domain (`GET api.example.com`), or the method alone                                                                        |
| `router`                    | Framework-specific, sometimes the raw URL (`SvelteKit Route Change`)                | The span's `http.route`, or `Router`                                                                                                      |
| `handler`                   | Framework-specific, often with the request method (`GET /users/:id`, `getUser`)     | The span's `http.route`, or `Request handler`                                                                                             |
| `graphql`                   | The phase and operation name (`query GetUser`, `graphql.resolve user.0.name`)       | The operation or processing type (`GraphQL query`, `GraphQL parse`)                                                                       |
| `gen_ai` inference ops      | `{operation} {model}`, or `{operation} unknown` (`chat unknown`)                    | `{operation} {model}`, or `{operation}` (`chat`)                                                                                          |
| `gen_ai.invoke_agent`       | The LangChain chain name, prefixed with `chain` (`chain format_prompt`)             | `{operation} {name}` from `gen_ai.agent.name`, `gen_ai.pipeline.name`, or `gen_ai.function_id`, or `{operation}`                          |
| `resource.*`                | The resource URL (`/assets/app.js`)                                                 | The resource domain (`cdn.example.com`), or `Resource`                                                                                    |
| `mcp.server`                | The method and its target (`resources/read file:///docs/api.md`)                    | The method alone for resource methods (`resources/read`). Tool and prompt names are unchanged                                             |
| `mcp.notification.*`        | The notification method name                                                        | The notification method name, or `MCP notification`                                                                                       |
| `queue.publish`             | Integration-specific (`publish my-exchange`, `send my-topic`)                       | The operation type and destination (`send my-exchange`), or the operation type alone                                                      |
| `queue.process`             | Integration-specific (`my-queue process`)                                           | The operation type and destination (`process my-queue`), or the operation type alone                                                      |
| `queue.receive`             | The kafkajs operation name (`poll my-topic`)                                        | The operation type and destination (`receive my-topic`)                                                                                   |
| `cache.*`                   | The cache keys (`user:123`), or for dataloader the operation and loader name        | The cache operation (`cache.get`, `cache.put`, `cache.remove`)                                                                            |
| `db`, `db.query` (SQL)      | The statement the driver ran (`SELECT * FROM "User" WHERE "id" = $1`)               | A summary of it (`SELECT "User"`), or, without a statement, the operation and table, the namespace, or the database system (`postgresql`) |
| `db` (MongoDB)              | The serialized command, or `mongodb.<operation>` (`mongodb.find`)                   | The operation and collection (`find users`), the database namespace, or `mongodb`                                                         |
| `db` (Mongoose)             | `mongoose.<Model>.<operation>` (`mongoose.BlogPost.findOne`)                        | The operation and collection (`findOne blogposts`), the database namespace, or `mongodb`                                                  |
| `db` (Supabase)             | The query builder call and table (`select(...) from(users)`), or `auth <method>`    | The operation and table (`select users`), or the dotted auth method (`auth.signInWithPassword`)                                           |
| `db.query` (Redis, ioredis) | The serialized command with redacted arguments (`set test-key [1 other arguments]`) | The operation and connection (`SET localhost:6379`), the operation and redis function for `FCALL`, or `redis`                             |

A few consequences worth checking:

* `useOperationNameForRootSpan` no longer renames the enclosing root span. The operations stay on that span's `sentry.graphql.operation` attribute.
* `graphqlClientIntegration` no longer appends the operation to the outgoing request span name. It's on `graphql.operation.name` and `graphql.operation.type` instead.
* Only the Express, Koa, and Hapi integrations resolve a route for `router` spans. Angular, Ember, and SvelteKit router spans are named `Router`.
* Express, Fastify, Hapi, and Elysia resolve a route for `handler` spans. NestJS has none at span start, so its handler spans are named `Request handler`. The handler function name moved to `nestjs.callback` for NestJS and `code.function.name` for Elysia.
* Cache keys are no longer part of a cache span name. They stay on `cache.key`, and every cache span carries the new `cache.operation` attribute (`get`, `put`, `remove`). This affects the Redis and ioredis cache spans, the Nuxt and Nitro storage spans, and the dataloader spans, which report the loader name on `db.collection.name` now. A Redis command matching `cachePrefixes` starts as a cache span now instead of turning into one at response time, and `maxCacheKeyLength` has no effect in stream mode.
* The `pg`, `postgres.js`, `mysql`, `mysql2`, `knex`, `tedious`, Prisma, Nitro `db0`, and Cloudflare D1 instrumentations name their query spans the same way now. A statement that touches no table (`SELECT NOW()`) summarizes to the bare operation. Connect and pool spans (`pg.connect`, `mysql2.connect`, `redis-connect`, `generic-pool.acquire`) keep their names.
* Supabase query spans drop the builder call from the name, and the modifiers stay on `db.query`. Auth spans are named after the method they call (`auth.admin.createUser`).
* AWS SQS `SendMessage`, `SendMessageBatch`, and `ReceiveMessage`, and SNS `Publish`, are messaging spans now instead of `rpc` spans. Every other command on those clients stays `rpc`.
* Child spans carry their service span's name in `sentry.segment.name`, so that changes with it.

`ignoreSpans` and `tracesSampler` both run when a span **starts**, so a span may not have its final name yet. Match on attributes instead:

```js
Sentry.init({
  // Before
  ignoreSpans: ["/health", "SELECT * FROM health_check"],
  tracesSampler: ({ name, inheritOrSampleWith }) =>
    inheritOrSampleWith(name === "GET /health" ? 0 : 1),

  // After
  ignoreSpans: [
    { attributes: { "sentry.op": "pageload", "url.path": "/health" } },
    { attributes: { "db.query.text": "SELECT * FROM health_check" } },
  ],
  tracesSampler: ({ attributes, inheritOrSampleWith }) =>
    inheritOrSampleWith(attributes["url.path"] === "/health" ? 0 : 1),
});
```

### The \`enableLogs\` option was removed

Action required

The `enableLogs` option was removed, including its `_experiments` variant. Logs are captured whenever you use their API (`Sentry.logger.*`) or add a logging integration such as `consoleLoggingIntegration()`.

```js
// Before
Sentry.init({
  enableLogs: true,
});

// After
Sentry.init({});
```

### The \`enableMetrics\` option was removed

Action required

The `enableMetrics` option was removed, including its `_experiments` variant. Metrics are captured whenever you use their API (`Sentry.metrics.*`). The `_experiments.beforeSendMetric` callback moved to the top-level `beforeSendMetric` option.

```js
// Before
Sentry.init({
  _experiments: {
    enableMetrics: true,
    beforeSendMetric: (metric) => metric,
  },
});

// After
Sentry.init({
  beforeSendMetric: (metric) => metric,
});
```

### \`@sentry/core\` API removals

Action required

The following APIs were removed:

* `Scope.clear()` was removed. To reset scope state, re-initialize the SDK or run your code in a fresh scope with `withScope` or `withIsolationScope`.
* The `disableInstrumentationWarnings` option and the `MissingInstrumentationContext` type were removed. With channel-based instrumentation, the SDK can no longer detect that a framework was imported before `Sentry.init()`.
* `createSpanEnvelope` and the `SpanEnvelope` and `SpanItem` types were removed. Standalone spans are gone: spans are sent on their transaction, or as streamed spans.
* The positional `spanOrigin` argument of `instrumentFetchRequest` was removed. Pass an options object as the last argument instead.
* The internal `addAutoIpAddressToUser` export was removed.

The low-level `propagateTrace` option of `getHttpClientSubscriptions` and `patchHttpModuleClient` is called `tracePropagation` now, matching the `httpIntegration` option of the same name.

### Console breadcrumbs moved to \`consoleIntegration\`

Action required

The `console` option of `breadcrumbsIntegration` was removed. Use `consoleIntegration` to capture console breadcrumbs.

### \`performance.mark()\` spans moved to \`userTimingIntegration\`

Action required

`browserTracingIntegration` no longer captures `performance.mark()` and `performance.measure()` spans by default. The `ignorePerformanceApiSpans` option moved to `userTimingIntegration` as `ignore`.

```js
// Before
Sentry.init({
  integrations: [
    Sentry.browserTracingIntegration({
      ignorePerformanceApiSpans: ["third-party-mark"],
    }),
  ],
});

// After
Sentry.init({
  integrations: [
    Sentry.browserTracingIntegration(),
    Sentry.userTimingIntegration({ ignore: ["third-party-mark"] }),
  ],
});
```

### Interaction spans moved to \`interactionsIntegration\`

Action required

The `_experiments.enableInteractions` option of `browserTracingIntegration` was removed. Use `interactionsIntegration()` instead.

```js
// Before
Sentry.init({
  integrations: [
    Sentry.browserTracingIntegration({
      _experiments: { enableInteractions: true },
    }),
  ],
});

// After
Sentry.init({
  integrations: [
    Sentry.browserTracingIntegration(),
    Sentry.interactionsIntegration(),
  ],
});
```

The `idleTimeout`, `finalTimeout`, and `childSpanTimeout` options of interaction spans are configured on `interactionsIntegration` now, with the same defaults as before.

### Standalone CLS and LCP span options were removed

Action required

The `_experiments.enableStandalone*Spans` options were removed. CLS and LCP are no longer configurable, and `browserTracingIntegration` no longer accepts an `_experiments` object at all.

CLS and LCP are recorded as measurements on the pageload span, or as dedicated spans in stream mode.

### \`trackFetchStreamPerformance\` moved to its own integration

Action required

The `trackFetchStreamPerformance` option of `browserTracingIntegration` was removed. Use `fetchStreamPerformanceIntegration()` instead.

```js
// Before
Sentry.init({
  integrations: [
    Sentry.browserTracingIntegration({
      trackFetchStreamPerformance: true,
    }),
  ],
});

// After
Sentry.init({
  integrations: [
    Sentry.browserTracingIntegration(),
    Sentry.fetchStreamPerformanceIntegration(),
  ],
});
```

### \`profilesSampleRate\` and \`profilesSampler\` were removed

Action required

The legacy per-transaction profiling options were removed. Configure [session-based profiling](https://docs.sentry.io/platforms/javascript/guides/vue/profiling.md) with `profileSessionSampleRate` and a `profileLifecycle` of `'trace'` or `'manual'` instead.

### AI integrations were removed from browser SDKs

Action required

AI integrations are no longer available in the browser SDK. They remain available in the server-side SDKs.

### \`InboundFilters\` was renamed to \`EventFilters\`

Action required

The `inboundFiltersIntegration` export was removed, and the integration reports itself as `EventFilters`. Update references by name, for example in `client.getIntegrationByName()`:

```js
// Before
Sentry.init({
  integrations: (integrations) =>
    integrations.filter((integration) => integration.name !== "InboundFilters"),
});

// After
Sentry.init({
  integrations: (integrations) =>
    integrations.filter((integration) => integration.name !== "EventFilters"),
});
```

## Verify behavior changes

9 left

Check dashboards and alerts.

### Browser sessions use \`unhandled\` instead of \`crashed\`

Behavior change

Sessions affected by an uncaught error are recorded as `unhandled` instead of `crashed`. If you track crash-free session rates or have alerts built on them, expect the rate to shift.

### \`page\` is the default browser session lifecycle mode

Behavior change

The `lifecycle` mode of `browserSessionIntegration` defaults to `'page'`, so a session is created on page load and is not renewed on navigation.

```js
// Restore a new session on load and on every navigation
Sentry.init({
  integrations: [Sentry.browserSessionIntegration({ lifecycle: "route" })],
});
```

### \`attachStacktrace\` now defaults to \`true\`

Behavior change

`Sentry.captureMessage()` events, and non-`Error` values passed to `Sentry.captureException()`, now attach a synthetic stack trace that points to the call site. Set `attachStacktrace: false` to restore the previous behavior.

Two consequences are worth checking after you upgrade:

* **Issue grouping:** Sentry groups events with and without stack traces differently, so you may see new issue groups.
* **Release health:** Events with a stack trace count as errors, so a `captureMessage()` call marks the current session as errored. Crash-free session rate is not affected. For purely informational output, consider [Sentry Logs](https://docs.sentry.io/product/logs.md) instead.

### \`tracePropagationTargets\` matching is now case-insensitive

Behavior change

String and regular expression matching for `tracePropagationTargets` no longer depends on casing. In browsers this was especially surprising, because the URL is normalized with `new URL()` before matching, which lower-cases the origin. A target such as `'myApi.com'` could therefore never match a request to `https://myApi.com`.

```js
Sentry.init({
  // In a browser, neither of these matched `https://myApi.com` in v10. In v11 both do.
  tracePropagationTargets: ["myApi.com", /^https:\/\/myApi\.com/],
});
```

If you relied on case-sensitive matching to tell two targets apart, narrow the target with a more specific path. The `g` and `y` flags are ignored now, because they made matching stateful and a target like `/myApi\.com/g` matched only every other request.

### Span attributes were renamed to match semantic conventions

Behavior change

Legacy span attributes were replaced by their semantic-convention equivalents. Update any custom instrumentation, `beforeSendSpan` logic, dashboards, or alerts that reference them.

HTTP and network attributes

| v10 attribute                          | v11 attribute                     |
| -------------------------------------- | --------------------------------- |
| `http.host`                            | `server.address`                  |
| `http.flavor`                          | `network.protocol.version`        |
| `http.client_ip`                       | `client.address`                  |
| `http.method`                          | `http.request.method`             |
| `http.status_code`                     | `http.response.status_code`       |
| `http.status_text`                     | `http.response.status_text`       |
| `http.scheme`                          | `url.scheme`                      |
| `http.user_agent`                      | `user_agent.original`             |
| `http.request_content_length`          | `http.request.body.size`          |
| `http.response_content_length`         | `http.response.body.size`         |
| `http.decoded_response_content_length` | `http.response.body.decoded_size` |
| `http.response_transfer_size`          | `http.response.size`              |
| `http.target`                          | `url.path` + `url.query`          |
| `http.query`                           | `url.query`                       |
| `http.fragment`                        | `url.fragment`                    |
| `url.same_origin`                      | `http.request.same_origin`        |
| `net.host.name`, `net.peer.name`       | `server.address`                  |
| `net.host.ip`                          | `network.local.address`           |
| `net.host.port`                        | `network.local.port`              |
| `net.peer.ip`                          | `network.peer.address`            |
| `net.peer.port`                        | `network.peer.port`               |
| `net.transport`                        | `network.transport`               |

`SanitizedRequestData`, the shape used for `http` breadcrumb data and `http.client` span data, uses `http.request.method` as the key for the request method now.

Transport values change from `ip_tcp` and `ip_udp` to `tcp` and `udp`. HTTP instrumentation reports the protocol as `network.protocol.name` and its version as `network.protocol.version`.

On server-side HTTP spans, the `content-length` header is always reported as `http.request.body.size` and `http.response.body.size`, instead of switching to `http.request_body_size_uncompressed` when no encoding was present.

Database and messaging attributes

| v10 attribute           | v11 attribute        |
| ----------------------- | -------------------- |
| `db.system`             | `db.system.name`     |
| `db.name`               | `db.namespace`       |
| `db.operation`          | `db.operation.name`  |
| `db.statement`          | `db.query.text`      |
| `db.mongodb.collection` | `db.collection.name` |
| `net.peer.name`         | `server.address`     |
| `net.peer.port`         | `server.port`        |

SQL query spans carry a new `db.query.summary` attribute, holding the summary of the sanitized statement (`SELECT "User"`). It's set in both trace lifecycles.

Mongoose spans report `db.system.name: 'mongodb'` instead of `'mongoose'`, because Mongoose is an ODM, not a database system.

The Redis and ioredis instrumentations no longer emit `db.connection_string`. The connection is described by `server.address` and `server.port` instead.

The AMQP instrumentation reports `messaging.destination.name`, `messaging.rabbitmq.destination.routing_key`, `messaging.message.id`, `messaging.message.conversation_id`, `messaging.operation.name`, `network.protocol.name`, `network.protocol.version`, and `url.full`. It no longer emits `messaging.destination_kind`.

Gen AI attributes

| v10 attribute                              | v11 attribute                              |
| ------------------------------------------ | ------------------------------------------ |
| `gen_ai.system`                            | `gen_ai.provider.name`                     |
| `gen_ai.request.available_tools`           | `gen_ai.tool.definitions`                  |
| `gen_ai.tool.input`                        | `gen_ai.tool.call.arguments`               |
| `gen_ai.tool.output`                       | `gen_ai.tool.call.result`                  |
| `gen_ai.usage.cache_creation_input_tokens` | `gen_ai.usage.cache_creation.input_tokens` |
| `gen_ai.usage.cache_read_input_tokens`     | `gen_ai.usage.cache_read.input_tokens`     |
| `gen_ai.usage.input_tokens.cached`         | `gen_ai.usage.cache_read.input_tokens`     |
| `gen_ai.usage.input_tokens.cache_write`    | `gen_ai.usage.cache_creation.input_tokens` |
| `gen_ai.usage.output_tokens.reasoning`     | `gen_ai.usage.reasoning.output_tokens`     |
| `ai.pipeline.name`                         | `gen_ai.pipeline.name`                     |
| `ai.streaming`                             | `gen_ai.response.streaming`                |
| `langchain.chain.name`                     | `gen_ai.pipeline.name`                     |

`gen_ai.tool.type` is no longer set on tool spans. `gen_ai.pipeline.name` is omitted for unnamed chains, instead of holding `unknown_chain`.

The Anthropic integration no longer sets `gen_ai.prompt`. The legacy Completions API prompt is reported as a user message on `gen_ai.input.messages`, like every other request shape.

Other attributes and constants

* On `ui.long_animation_frame` spans, `code.filepath` and `code.function` became `code.file.path` and `code.function.name`.
* On `file` spans, `fs_error` became `error.type` and holds the syscall error code (`ENOENT`) instead of the full message.
* The TanStack Router integration reports path parameters as `url.path.parameter.<key>` instead of `url.path.params.<key>`.
* The Cloudflare-specific `sentry.cloudflare_tracer` attribute is no longer set.
* Import attribute constants from `@sentry/core` directly. The `semanticAttributes` re-export was removed.
* `SEMANTIC_ATTRIBUTE_SENTRY_SOURCE` (`sentry.source`) was replaced by `SENTRY_SEGMENT_NAME_SOURCE` (`sentry.segment.name.source`), which is only set on the root span.

### Span operations were consolidated

Behavior change

Span ops are now a smaller, framework-neutral set. The detail that used to live in the op, such as the framework, library, method name, or lifecycle phase, is preserved in attributes like `code.function.name`, `sentry.origin`, `db.system.name`, `db.operation.name`, and `faas.trigger`.

Update anything that filters, groups, or alerts on span ops: dashboards, dynamic sampling rules, `ignoreSpans`, and `beforeSendSpan`. TypeScript doesn't catch these.

Full list of span op changes

**Backend HTTP, handlers, middleware, and routers**

| Area                                                              | Before                                                                                                                                                                                                                     | After         |
| ----------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------- |
| Request handlers (Express, Koa, Connect, Fastify, Elysia, NestJS) | `request_handler.<library>`, `handler.nestjs`                                                                                                                                                                              | `handler`     |
| Hono `app.request()` in-process dispatch                          | `hono.request`                                                                                                                                                                                                             | `http.server` |
| Web-server middleware                                             | `middleware.express`, `middleware.koa`, `middleware.hono`, `middleware.elysia`, `middleware.nestjs`, `middleware.nuxt`, `middleware.nitro`, `middleware.tanstackstart`, `hook.fastify`, `http.server.middleware` (Next.js) | `middleware`  |
| Backend router layers                                             | `router.express`, `router.koa`, `router.hapi`                                                                                                                                                                              | `router`      |
| Hapi server extensions                                            | `server.ext.hapi`                                                                                                                                                                                                          | `middleware`  |
| NestJS setup and lifecycle handlers                               | `app_creation.nestjs`, `request_context.nestjs`, `event.nestjs`                                                                                                                                                            | `function`    |

**Framework functions**

| Area                                                                                                         | Before                                                                                                                                                                                              | After      |
| ------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
| Loaders, actions, and server functions (Next.js, Remix, React Router, SvelteKit, SolidStart, TanStack Start) | `function.nextjs`, `function.sveltekit.load`, `function.react_router.loader`, `function.remix.document_request`, `loader.remix`, `action.remix`, `function.server_action`, `function.tanstackstart` | `function` |

**Frontend and UI**

| Area                                        | Before                                                                                                                               | After                                                    |
| ------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------- |
| Frontend routing                            | `ui.angular.routing`, `ui.sveltekit.routing`, `ui.ember.transition`                                                                  | `router`                                                 |
| React, Vue, and Svelte component lifecycles | `ui.react.mount`/`render`/`update`, `ui.svelte.init`/`update`, Vue `render`/`update`/`mount`/`create`/`activate`/`unmount`/`destroy` | `ui.mount`, `ui.render`, `ui.update`, `ui.unmount`       |
| Angular tracing decorators                  | `ui.angular.init`, `ui.angular.<method>`                                                                                             | `ui.mount`, `function`                                   |
| Ember route hooks, runloop, and components  | `ui.ember.route.<hook>`, `ui.ember.runloop.<queue>`, `ui.ember.component.render`/`definition`/`init`                                 | `function`, `ui.task`, `ui.render`/`function`/`ui.mount` |
| Browser paint entries                       | `paint`                                                                                                                              | `browser.paint`                                          |

**Databases, cache, and messaging**

| Area                                     | Before                                                                                                                                           | After                                             |
| ---------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------- |
| Redis commands and connect               | `db.redis`, `db.redis.connect`                                                                                                                   | `db.query`, `db`                                  |
| Nuxt and Nitro storage (unstorage)       | `cache.has_item`, `cache.get_item`, `cache.get_items`, `cache.get_keys`, `cache.set_item`, `cache.set_items`, `cache.remove_item`, `cache.clear` | `cache.get`, `cache.put`, `cache.remove`          |
| Kafka, AMQP, and OTel-inferred messaging | `message`, `message.produce`, `message.consume`                                                                                                  | `queue.publish`, `queue.receive`, `queue.process` |
| AWS SQS and SNS messaging commands       | `rpc`                                                                                                                                            | `queue.publish`, `queue.receive`                  |

**RPC and Gen AI**

| Area                                                       | Before                                      | After                                    |
| ---------------------------------------------------------- | ------------------------------------------- | ---------------------------------------- |
| tRPC                                                       | `rpc.server`                                | `rpc`                                    |
| GCP gRPC calls                                             | `grpc.<service>`                            | `grpc`                                   |
| AWS Bedrock inference                                      | `rpc`                                       | `gen_ai.chat`, `gen_ai.generate_content` |
| Gen AI fallbacks and model metadata (Vercel AI, LangGraph) | `gen_ai.unknown`, `ai.run`, `gen_ai.models` | `function`                               |

**FaaS, serverless, and HTTP clients**

| Area                                           | Before                                                                | After                                      |
| ---------------------------------------------- | --------------------------------------------------------------------- | ------------------------------------------ |
| AWS Lambda functions                           | `function.aws.lambda`                                                 | `function.aws`                             |
| GCP functions                                  | `function.gcp.http`, `function.gcp.event`, `function.gcp.cloud_event` | `function.gcp`                             |
| Firebase functions                             | `http.request`                                                        | `function.gcp`                             |
| Cloudflare cron, email, and workflow steps     | `faas.cron`, `faas.email`, `function.step.do`                         | `function`                                 |
| OTel-inferred FaaS spans (from `faas.trigger`) | arbitrary trigger strings used verbatim                               | `http.server`, `queue.process`, `function` |
| GCP HTTP client                                | `http.client.<service>`                                               | `http.client`                              |
| Prefetch HTTP requests                         | `http.client.prefetch`, `http.server.prefetch`                        | `http.client`, `http.server`               |

**Casing normalized to snake\_case**

| Before                          | After                              |
| ------------------------------- | ---------------------------------- |
| `ui.long-task`                  | `ui.long_task`                     |
| `ui.long-animation-frame`       | `ui.long_animation_frame`          |
| `browser.unloadEvent`           | `browser.unload_event`             |
| `browser.domContentLoadedEvent` | `browser.dom_content_loaded_event` |
| `browser.loadEvent`             | `browser.load_event`               |
| `browser.TLS/SSL`               | `browser.tls_ssl`                  |
| `browser.DNS`                   | `browser.dns`                      |

### INP is always sent as a web vital span

Behavior change

INP is always sent as a web vital span, carrying its value in the `browser.web_vital.inp.value` attribute instead of as a span measurement. Update custom dashboards and alerts that read it as a measurement (built-in dashboards do not need adjustments).

### The \`DOMException.code\` tag was removed

Behavior change

Events created from a `DOMException` no longer carry a `DOMException.code` tag, because the `code` property is deprecated in favor of `DOMException.name`, which is already the exception type. Switch searches and alert rules that use the tag to `error.type`.

### \`sendFeedback\` rejects with an \`Error\`

Behavior change

`Sentry.sendFeedback()` now rejects with an `Error` in all cases. Previously it rejected with a plain string when the request timed out, was rejected with a 403, or otherwise failed to send. The message text is unchanged and is still customizable through the `errorMessages` hint, so read it from `error.message`.

## Optional cleanup

2 left

Deprecations and type tightening you can address later.

### Type changes

FYI

Several public types changed:

* Several public types that used `any` now use `unknown`, including `StackFrame`, `SamplingContext`, `SentryError`, and `User`. You may need to narrow types explicitly.
* Attribute typing and serialization were unified across the SDK.
* The `attributes` field of the `SamplingContext` passed to `tracesSampler` is required now. The SDK always provides it, so this only affects code that narrows or builds `SamplingContext` objects by hand.
* The `attributes` field of `ScopeData` is required now. This only affects code that constructs `ScopeData` objects manually: add `attributes: {}` there.
* The `endTimestamp` property was removed from `SentrySpanArguments`. Call `span.end(timestamp)` instead.
* `BrowserOptions` supports the `TransportOptions` generic now.

### \`withStreamedSpan()\` is now a no-op

FYI

If you wrapped `beforeSendSpan` with `withStreamedSpan()` to opt into the streamed payload in v10, drop the wrapper. It's a no-op now that streamed payloads are the default, and it's deprecated.
