Migrate from 8.x to 9.x
Learn about migrating from Sentry JavaScript SDK 8.x to 9.x
Version 9 of the Sentry JavaScript SDK primarily introduces API cleanup and version support changes.
This update contains behavioral changes that will not be caught by type checkers, linters, or tests, so we recommend carefully reading through the entire migration guide instead of relying on automatic tooling.
Version 9 of the SDK is compatible with Sentry self-hosted versions 24.4.2 or higher (unchanged from v8). Lower versions may continue to work, but may not support all features.
Version 9 of the Sentry SDK has new compatibility ranges for runtimes and frameworks.
All the JavaScript code in the Sentry SDK packages may now contain ECMAScript 2020 features. This includes features like Nullish Coalescing (??), Optional Chaining (?.), String.matchAll(), Logical Assignment Operators (&&=, ||=, ??=), and Promise.allSettled().
If you observe failures due to syntax or features listed above, it may indicate that your current runtime does not support ES2020. If your runtime does not support ES2020, we recommend transpiling the SDK using Babel or similar tools.
The minimum supported Node.js version is 18.0.0 (Released Apr 19, 2022), except for ESM-only SDKs (@sentry/astro, @sentry/nuxt, @sentry/sveltekit) which require Node.js version 18.19.1 (Released Feb 14, 2024) or higher.
Due to SDK code now including ES2020 features, the minimum supported browser list now looks as follows:
- Chrome 80 (Released Feb 5, 2020)
- Edge 80 (Released Feb 7, 2020)
- Safari 14, iOS Safari 14.4 (Released Sep 16, 2020)
- Firefox 74 (Released Mar 10, 2020)
- Opera 67 (Released Mar 12, 2020)
- Samsung Internet 13.0 (Released Nov 20, 2020)
If you need to support older browsers, we recommend transpiling your code using SWC, Babel or similar tools.
In preparation for v2 of the OpenTelemetry SDK, the minimum required TypeScript version is increased to version 5.0.4.
Additionally, like the OpenTelemetry SDK, the Sentry JavaScript SDK will follow DefinitelyType's version support policy which has a support time frame of 2 years for any released version of TypeScript.
Older TypeScript versions may continue to be compatible, but no guarantees apply.
- Prisma version 5.xand below are no longer supported (minimum supported version is6.x).
The changes outlined in this section describe in what way the SDK may behave differently after upgrading:
- Dropping spans in the - beforeSendSpanhook is no longer possible. This means you can no longer return- nullfrom the- beforeSendSpanhook. This hook is intended to be used to add additional data to spans or remove unwanted attributes (for example for PII stripping). To control which spans are recorded, we recommend configuring integrations instead.
- The - beforeSendSpanhook now receives the root span as well as the child spans. We recommend checking your- beforeSendSpanto account for this change.
- The - requestproperty on the- samplingContextargument passed to the- tracesSamplerand- profilesSampleroptions has been removed.- samplingContext.normalizedRequestcan be used instead. Note that the type of- normalizedRequestdiffers from- request.
- The - startSpanbehavior was changed if you pass a custom- scope: While in v8, the passed scope was set active directly on the passed scope, in v9, the scope is cloned. This behavior change does not apply to- @sentry/nodewhere the scope was already cloned. This change was made to ensure that the span only remains active within the callback and to align behavior between- @sentry/nodeand all other SDKs. As a result of the change, span hierarchy should be more accurate. However, modifying the scope (for example, set tags) within the- startSpancallback behaves a bit differently now.Copied- startSpan({ name: "example", scope: customScope }, () => { // This tag will only remain within the callback. getCurrentScope().setTag("tag-a", "a"); // Set the tag directly on customScope in addition, // if you want to to persist the tag outside of the callback. customScope.setTag("tag-a", "a"); });
- Passing - undefinedas a- tracesSampleRateoption value will now be treated the same as if the attribute was not defined at all. In previous versions, it was checked whether the- tracesSampleRateproperty existed in the SDK options to decide if trace data should be propagated for tracing. Consequentially, this sometimes caused the SDK to propagate negative sampling decisions when- tracesSampleRate: undefinedwas passed. This is no longer the case and sampling decisions will be deferred to downstream SDKs for distributed tracing. This is more of a bugfix rather than a breaking change, however, depending on the setup of your SDKs, an increase in sampled traces may be observed.
- If you use the optional - captureConsoleIntegrationand set- attachStacktrace: truein your- Sentry.initcall, console messages will no longer be marked as unhandled (- handled: false) but as handled (- handled: true). If you want to keep sending them as unhandled, configure the- handledoption when adding the integration:Copied- Sentry.init({ integrations: [Sentry.captureConsoleIntegration({ handled: false })], attachStacktrace: true, });
- The SDK no longer instructs the Sentry backend to automatically infer IP addresses by default. Depending on the version of the Sentry backend (self-hosted), this may lead to IP addresses no longer showing up in Sentry, and events being grouped to "anonymous users". At the time of writing, the Sentry SaaS solution will still continue to infer IP addresses, but this will change in the near future. Set sendDefaultPii: trueinSentry.init()to instruct the Sentry backend to always infer IP addresses.
- The - tracesSamplerhook will no longer be called for every span. Root spans may however have incoming trace data from a different service, for example when using distributed tracing.
- The - requestDataIntegrationwill no longer automatically set the user from- request.userwhen- expressis used. Starting in v9, you'll need to manually call- Sentry.setUser()e.g. in a middleware to set the user on Sentry events.
- The - processThreadBreadcrumbIntegrationwas renamed to- childProcessIntegration.
- The - childProcessIntegration's (previously- processThreadBreadcrumbIntegration)- namevalue has been changed from- "ProcessAndThreadBreadcrumbs"to- "ChildProcess". Any filtering logic for registered integrations should be updated to account for the changed name.
- The - vercelAIIntegration's- namevalue has been changed from- "vercelAI"to- "VercelAI"(capitalized). Any filtering logic for registered integrations should be updated to account for the changed name.
- The Prisma integration no longer supports Prisma v5 and supports Prisma v6 by default. As per Prisma v6, the - previewFeatures = ["tracing"]client generator option in your Prisma Schema is no longer required to use tracing with the Prisma integration.- For performance instrumentation using other/older Prisma versions: - Install the - @prisma/instrumentationpackage with the desired version.
- Pass a - new PrismaInstrumentation()instance as exported from- @prisma/instrumentationto the- prismaInstrumentationoption of this integration:Copied- import { PrismaInstrumentation } from "@prisma/instrumentation"; Sentry.init({ integrations: [ prismaIntegration({ // Override the default instrumentation that Sentry uses prismaInstrumentation: new PrismaInstrumentation(), }), ], });- The passed instrumentation instance will override the default instrumentation instance the integration would use, while the - prismaIntegrationwill still ensure data compatibility for the various Prisma versions.
- Depending on your Prisma version (prior to Prisma version 6), add - previewFeatures = ["tracing"]to the client generator block of your Prisma schema:Copied- generator client { provider = "prisma-client-js" previewFeatures = ["tracing"] }
 
- When - skipOpenTelemetrySetup: trueis configured,- httpIntegration({ spans: false })will be configured by default. You no longer have to specify this manually. With this change, no spans are emitted once- skipOpenTelemetrySetup: trueis configured, without any further configuration being needed.
The @sentry/utils package will no longer be published.
The @sentry/types package will continue to be published, however, it is deprecated and its API will not be extended. It will not be published as part of future major versions.
All exports and APIs of @sentry/utils and @sentry/types (except for the ones that are explicitly called out in this migration guide to be removed) have been moved into the @sentry/core package.
The changes outlined in this section detail deprecated APIs that are now removed.
- The metrics API has been removed from the SDK. - The Sentry metrics beta has ended and the metrics API has been removed from the SDK. Learn more in the Sentry help center docs. 
- The - transactionContextproperty on the- samplingContextargument passed to the- tracesSamplerand- profilesSampleroptions has been removed. All object attributes are available in the top-level of- samplingContext:Copied- Sentry.init({ // Custom traces sampler tracesSampler: samplingContext => { - if (samplingContext.transactionContext.name === '/health-check') { + if (samplingContext.name === '/health-check') { return 0; } else { return 0.5; } }, // Custom profiles sampler profilesSampler: samplingContext => { - if (samplingContext.transactionContext.name === '/health-check') { + if (samplingContext.name === '/health-check') { return 0; } else { return 0.5; } }, })
- The - enableTracingoption was removed. Instead, set- tracesSampleRate: 1or- tracesSampleRate: 0.
- The - autoSessionTrackingoption was removed.- To enable session tracking, ensure that either, in browser environments the - browserSessionIntegrationis added, or in server environments the- httpIntegrationis added. (both are added by default)- To disable session tracking, remove the - browserSessionIntegrationin browser environments, or in server environments configure the- httpIntegrationwith the- trackIncomingRequestsAsSessionsoption set to- false. Additionally, in Node.js environments, a session was automatically created for every node process when- autoSessionTrackingwas set to- true. This behavior has been replaced by the- processSessionIntegrationwhich is configured by default.
- The - getCurrentHub(),- Huband- getCurrentHubShim()APIs have been removed. They were on compatibility life support since the release of v8 and have now been fully removed from the SDK.
- The - addOpenTelemetryInstrumentationmethod has been removed. Use the- openTelemetryInstrumentationsoption in- Sentry.init()or your custom Sentry Client instead.Copied- import * as Sentry from "@sentry/node"; // before Sentry.addOpenTelemetryInstrumentation(new GenericPoolInstrumentation()); // after Sentry.init({ openTelemetryInstrumentations: [new GenericPoolInstrumentation()], });
- The - debugIntegrationhas been removed. To log outgoing events, use Hook Options (- beforeSend,- beforeSendTransaction, ...).
- The - sessionTimingIntegrationhas been removed. To capture session durations alongside events, use Context (- Sentry.setContext()).
- The - addOpenTelemetryInstrumentationmethod was removed. Use the- openTelemetryInstrumentationsoption in- Sentry.init()or your custom Sentry Client instead.
- registerEsmLoaderHooksnow only accepts- true | false | undefined. The SDK will default to wrapping modules that are used as part of OpenTelemetry Instrumentation.
- The - nestIntegrationwas removed. Use the NestJS SDK (- @sentry/nestjs) instead.
- The - setupNestErrorHandlerwas removed. Use the NestJS SDK (- @sentry/nestjs) instead.
- The captureUserFeedbackmethod has been removed. Use thecaptureFeedbackmethod instead and update thecommentsfield tomessage.
- The CJS code for the SDK now only contains compatibility statements for CJS/ESM in modules that have default exports: Copied- Object.defineProperty(exports, "__esModule", { value: true });- Let us know if this is causing issues in your setup by opening an issue on GitHub. 
- @sentry/denois no longer published on the- deno.landregistry, so you'll need to import the SDK from npm:Copied- import * as Sentry from "npm:@sentry/deno"; Sentry.init({ dsn: "__DSN__", // ... });
- Scopeusages now always expect- Scopeinstances.
- Clientusages now always expect- BaseClientinstances. The abstract- Clientclass was removed. Client classes now have to extend from- BaseClient.
These changes should not affect most users unless you relied on passing things with a similar shape to internal methods.
In v8, interfaces have been exported from @sentry/types, while implementations have been exported from other packages.
The following changes are unlikely to affect users of the SDK. They are listed here only for completion sake, and to alert users that may be relying on internal behavior.
- A - sampleRandfield on- PropagationContextis now required. This is relevant if you used- scope.setPropagationContext(...)
- The - DEFAULT_USER_INCLUDESconstant has been removed. There is no replacement.
- The - BAGGAGE_HEADER_NAMEexport has been removed. Use a- "baggage"string constant directly instead.
- The - extractRequestDatamethod has been removed. Manually extract relevant data of request objects instead.
- The - addRequestDataToEventmethod has been removed. Use- httpRequestToRequestDatainstead and put the resulting object directly on- event.request.
- The - addNormalizedRequestDataToEventmethod has been removed. Use- httpRequestToRequestDatainstead and put the resulting object directly on- event.request.
- The - generatePropagationContext()method was removed. Use- generateTraceId()directly.
- The - spanIdfield on- propagationContextwas removed. It was replaced with an optional field- propagationSpanIdhaving the same semantics but only being defined when a unit of execution should be associated with a particular span ID.
- The - initSessionFlushermethod on the- ServerRuntimeClientwas removed without replacements. Any mechanisms creating sessions will flush themselves.
- The - IntegrationClasstype was removed. Instead, use- Integrationor- IntegrationFn.
- The following exports have been removed without replacement: - getNumberOfUrlSegments
- validSeverityLevels
- makeFifoCache
- arrayify
- flatten
- urlEncode
- getDomElement
- memoBuilder
- extractPathForTransaction
- _browserPerformanceTimeOriginMode
- addTracingHeadersToFetchRequest
- SessionFlusher
 
- The following types have been removed without replacement: - Request- RequestEventData
- TransactionNamingScheme
- RequestDataIntegrationOptions
- SessionFlusherLike
- RequestSession
- RequestSessionStatus
 
- Removed - getPropagationContextFromSpanwithout replacement.
- Removed - generateSpanContextForPropagationContextwithout replacement.
- client._prepareEvent()now requires both- currentScopeand- isolationScopeto be passed as arguments.
- client.recordDroppedEvent()no longer accepts an- eventas a third argument. The event was no longer used for some time, instead you can (optionally) pass a count of dropped events as a third argument.
Version support timelines are stressful for everybody using the SDK, so we won't be defining one. Instead, we will be applying bug fixes and features to older versions as long as there is demand.
Additionally, we hold ourselves accountable to any security issues, meaning that if any vulnerabilities are found, we will in almost all cases backport them.
Note, that backporting decisions are made on a case-by-case basis. If you need a fix or feature in a previous version of the SDK, please reach out via a GitHub Issue.
Our documentation is open source and available on GitHub. Your contributions are welcome, whether fixing a typo (drat!) or suggesting an update ("yeah, this would be better").