Skip to content

@sentry/nuxt: maps removed by filesToDeleteAfterUpload stay in Nitro's public-asset manifest, so /_nuxt/*.js.map returns 500 instead of 404 #25242

Closed

Description

@mketiku

Is there an existing issue for this?

How do you use Sentry?

Sentry SaaS (sentry.io)

Which SDK are you using?

@sentry/nuxt

SDK Version

11.6.0 (also reproduced on 10.75.0)

Framework Version

Nuxt 3.21.11, nitropack 2.13.4, node-server preset, Node 22

Link to Sentry event

n/a

Reproduction Example/SDK Setup

// nuxt.config.ts
export default defineNuxtConfig({
  modules: ['@sentry/nuxt/module'],
  sourcemap: { client: 'hidden' },
  sentry: {
    org: '...',
    project: '...',
    sourcemaps: {
      filesToDeleteAfterUpload: ['.output/public/**/*.map'],
    },
  },
});

No auth token is needed to reproduce, because the deletion runs either way.

Steps to Reproduce

  1. nuxt build
  2. find .output/public -name '*.map' finds nothing, because the maps were deleted.
  3. grep -o '"/_nuxt/[^"]*\.js\.map"' .output/server/chunks/nitro/nitro.mjs | head still lists every map in Nitro's public-asset manifest.
  4. node .output/server/index.mjs
  5. Request a real chunk with curl -i localhost:3000/_nuxt/<chunk>.js, then the same URL with .map appended: curl -i localhost:3000/_nuxt/<chunk>.js.map.

Expected Result

The .map request returns 404, the same as an unknown path (/_nuxt/doesnotexist.js.map already returns 404).

Actual Result

The .map request returns 500, with the server log showing:

[request error] [unhandled] [GET] http://localhost:3000/_nuxt/<chunk>.js.map
 H3Error: ENOENT: no such file or directory, open '.../.output/public/_nuxt/<chunk>.js.map'

The 500 response also carries the deleted file's ETag, its Content-Length, and Cache-Control: public, max-age=31536000, immutable, all taken from the stale manifest entry.

Additional Context

Ordering problem:

  1. @nuxt/nitro-server copies the client build into .output/public in Nitro's rollup:before hook (dist/index.mjs:780-783: copyPublicAssets, then nitro:build:public-assets).
  2. Nitro then globs .output/public into the virtual #nitro-internal-virtual/public-assets-data manifest (nitropack/dist/rollup/index.mjs ~L1232) and bundles it into the server.
  3. @sentry/nuxt deletes the files in Nuxt's close hook, after the server bundle exists (build/module/module.mjs L620-623 in 11.6.0, deleteSourceMapsAfterBuild).
  4. At runtime the static handler finds the manifest entry, sets headers, and calls readAsset, which runs fsp.readFile and throws ENOENT. That surfaces as a 500 (nitropack/dist/runtime/internal/static.mjs).

The automatic deletion fallback (when filesToDeleteAfterUpload is unset) uses the same close hook, so it should behave the same way.

hidden maps (#13993) stop browsers from requesting maps, but crawlers and scanners still request them. They get 500s, and Sentry's own server SDK reports those 500s as errors. Another project diagnosed the same chain independently after a bot requested about 47 maps and triggered an alert burst (kodes-agency/reputation-key#631).

Workaround we use, which removes the maps after the copy and before the manifest is built:

hooks: {
  async 'nitro:build:public-assets'(nitro) {
    const { readdir, rm } = await import('node:fs/promises');
    const { join } = await import('node:path');
    const dir = nitro.options.output.publicDir;
    const files = await readdir(dir, { recursive: true });
    await Promise.all(files.filter(f => f.endsWith('.map')).map(f => rm(join(dir, f))));
  },
},

The client upload is unaffected because the Vite plugin uploads from .nuxt/dist/client at writeBundle, before Nitro runs. We confirmed in production that the upload succeeds and the URLs return 404. nitro.ignore: ['**/*.map'] does not work, because Nuxt appends !<buildDir>/dist/client/_nuxt/**/* to nitro.ignore (@nuxt/nitro-server/dist/index.mjs:400).

Suggested fix: for client maps, have the module delete in nitro:build:public-assets (or exclude *.map when Nitro builds the manifest) instead of in close. Server maps can keep the current timing.

Priority

Low. Nothing leaks, but it produces stray 500s and alert noise.

Activity

  1. linear-code commented on Oct 9, 2026

    @linear-code
  2. self-assigned this
    on Oct 12, 2026
  3. s1gr1d commented on Oct 12, 2026

    @s1gr1d
    Member

    Hi, thanks for reporting. We just released a fix regarding the source maps upload. This was released in 11.5.0 and 10.76.1. But you are mentioning a version without this fix and one with it. Taking a look - probably this is unrelated.

    #25080

  4. moved this from Waiting for: Product Owner to No status in GitHub Issues with 👀 3on Oct 12, 2026
  5. self-assigned this
    on Oct 12, 2026
  6. added a commit that references this issue on Oct 12, 2026
    36fdc3f
  7. github-actions commented on Oct 12, 2026

    @github-actions
    Contributor

    A PR closing this issue has just been released 🚀

    This issue was referenced by PR #25267, which was included in the 11.7.0 release.

  8. mketiku commented on Oct 12, 2026

    @mketiku
    ContributorAuthor

    Confirmed fixed on 11.7.0, thanks! Same setup as the report (Nuxt 3.21.11, nitropack 2.13.4, node-server, sourcemap: { client: 'hidden' }, filesToDeleteAfterUpload: ['.output/public/**/*.map']), with our nitro:build:public-assets workaround removed:

    • 11.6.0: 259 deleted maps still in the public-asset manifest; /_nuxt/<chunk>.js.map → 500 (ENOENT)
    • 11.7.0: 0 maps in the manifest; /_nuxt/<chunk>.js.map → 404

    Now running 11.7.0 in production without the workaround.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions