Skip to content

Function names remain mangled in Sentry stack traces after upgrading to Next.js 16 + Turbopack #18248

Open

Description

@rui-reevo

Is there an existing issue for this?

How do you use Sentry?

Sentry Saas (sentry.io)

Which SDK are you using?

@sentry/nextjs

SDK Version

10.25.0

Framework Version

Next 16.0.3

Link to Sentry event

https://reevo-v7.sentry.io/issues/7041925983/events/1293cbdf13f54015b7cdde21ec9056de/

Reproduction Example/SDK Setup

// instrumentation-client.ts
Sentry.init({
  dsn: '',
  environment: loggerEnv,
  integrations: [
    Sentry.replayIntegration({
      maskAllText: false,
    }),
    Sentry.browserTracingIntegration(),
  ],
  tracesSampleRate: 1,
  replaysSessionSampleRate: 0,
  replaysOnErrorSampleRate: 1.0,
  enabled: true,
});

Steps to Reproduce

  1. Build and deploy — I’ve checked and the sourcemap is definitely being generated and shipped.
  2. Trigger the error and take a look at the stack trace in the Sentry UI.

Expected Result

With sourcemaps, the stack trace will show the real source code and the actual function name.

Actual Result

The code shows up correctly as source, but the function name is still mangled—just like in the raw stack trace.

Additional Context

No response

Priority

React with 👍 to help prioritize this issue. Please use comments to provide useful context, avoiding +1 or me too, to help us triage it.

Activity

  1. linear commented on Nov 19, 2025

    @linear
  2. moved this to Waiting for: Product Owner in GitHub Issues with 👀 3on Nov 19, 2025
  3. rui-reevo commented on Nov 19, 2025

    @rui-reevo
    Author

    Looks like the problem is tied to Turbopack — switching back to Webpack makes it go away. Any ideas on how to work around this?

  4. JPeer264 commented on Nov 19, 2025

    @JPeer264
    Member

    Hey @rui-reevo I just confirmed this with Turbopack (yes, with Webpack it does work). The fastest workaround is to use Webpack for now, or rely on Turbopack in the combination of the line of code.

    I'll leave this picture here for the record:

    Turbopack:
    Image

    vs Webpack:

    Image
  5. moved this from Waiting for: Product Owner to No status in GitHub Issues with 👀 3on Nov 19, 2025
  6. self-assigned this
    on Nov 19, 2025
  7. chargome commented on Nov 19, 2025

    @chargome
    Member

    Hey @rui-reevo we're aware of this, this will require a change in our symbolication pipeline. I'll leave this issue open for now 👍

  8. rui-reevo commented on Dec 9, 2025

    @rui-reevo
    Author

    any updates on this? ty

  9. 29 remaining items

  10. moved this from Waiting for: Product Owner to No status in GitHub Issues with 👀 3on Feb 6, 2026
  11. rui-reevo commented on May 11, 2026

    @rui-reevo
    Author

    Hey @chargome, just wanted to check in — we're still hitting this issue on Next.js 16.2.3 with _experimental.turbopackReactComponentAnnotation.enabled set for Turbopack. Any updates on where things stand? It's been pretty painful on our end.

  12. moved this to Waiting for: Product Owner in GitHub Issues with 👀 3on May 11, 2026
  13. chargome commented on May 11, 2026

    @chargome
    Member

    Hey @rui-reevo I think we're still waiting on Vercel for an upstream fix here. I'll check again and ping them

  14. moved this from Waiting for: Product Owner to No status in GitHub Issues with 👀 3on May 11, 2026
  15. moved this to Waiting for: Product Owner in GitHub Issues with 👀 3on Sep 16, 2026
  16. digitalcostas commented on Sep 16, 2026

    @digitalcostas

    Same symptom on the server side, with a measurement of where the name is lost. It doesn't look
    like an SDK defect: the maps Sentry receives carry no names entry for the mangled bindings.

    Setup

    • Next.js 16.3.3 (Turbopack, the default bundler), @sentry/nextjs 10.73.0, Node 24, on Vercel
    • Server source maps upload and match. Every first-party frame resolves the right file, line and
      source-context line; only the function names are wrong.

    What the frames look like (symbol and path names generalized):

    Frame as Sentry shows it Resolves to Context line
    W app/api/.../route.ts:228 await deprovisionThing(...)
    H lib/.../deprovision-thing.ts:172 capture('remove', ...)
    $ lib/.../deprovision-thing.ts:168 captureStageFailure(...)
    <anonymous> lib/.../capture-stage-failure.ts:27 Sentry.captureException(...)

    Where the name is lost

    next build with SENTRY_AUTH_TOKEN unset, then inspect the emitted chunk map. Turbopack writes
    sectioned maps, so the check has to flatten first:

    // node, from the repo root, after `next build`
    const fs = require('fs')
    const { FlattenMap, originalPositionFor } = require('@jridgewell/trace-mapping')
    // find the chunk with: grep -rl '<a string literal from the function>' .next/server/chunks
    const map = new FlattenMap(JSON.parse(fs.readFileSync(chunk + '.map', 'utf8')))
    originalPositionFor(map, { line, column /* of the mangled identifier */ })
    // → { source, line, column, name: null }   ← the defect
    1. export async function deprovisionThing(…) is emitted as async function z(e){…}. The mapping
      at token z points exactly at the original identifier in the source, and carries name: null.
    2. const capture = (…) => … is emitted as U=(e,a,r)=>…; mapping correct, name: null again.
    3. That chunk map's names table holds 244 entries and contains none of the mangled bindings'
      original names. The entries it does hold are property keys and unmangled identifiers.
    4. Exported functions are additionally emitted as anonymous function expressions inside the
      module's export call, e.s(["captureStageFailure",0,function(e){…}]), so V8 itself reports
      <anonymous>; there is no name token there for any consumer to map.

    So symbolication has nothing to recover from. Per Sentry's own description of the scope-based
    approach (https://blog.sentry.io/how-we-made-javascript-stack-traces-awesome — "For each of these
    individual components, we do a lookup in the provided source map. And if the source map is
    properly constructed, we will get a name back"), the lookup at the minified identifier returns
    null, so the minified name stands. Re-uploading or widening the upload globs changes nothing —
    matching already works.

    Things that don't work around it on 16.3.x

    • experimental.serverMinification: false — accepted by the config schema, and Turbopack's
      unsupported-options list doesn't reject it, but it's a no-op: the rebuilt server output was
      byte-identical (same chunk hashes, same total byte count), and the key is absent from
      next-swc.<platform>.node. Only the webpack build honours it.
    • experimental.turbopackMinify: false — works, but it's global, so it un-minifies the client
      bundles too.

    The underlying gap looks like Turbopack's minifier: it mangles bindings without recording the
    original names in the map's names table, so there's nothing for scope-based name recovery to
    look up. Next.js canary has widened experimental.turbopackMinify to a per-environment form
    ({ server, client, edge }), which lets a server build skip minification, but that sidesteps the
    defect rather than fixing it, and client bundles would still lose their names.

  17. chargome commented on Sep 18, 2026

    @chargome
    Member

    @digitalcostas yeah this has been established already in vercel/next.js#87896

    We'll get back on it with the vercel team

  18. moved this from Waiting for: Product Owner to No status in GitHub Issues with 👀 3on Sep 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions