Skip to content

fix(nuxt): Split the Nitro error hook as Nuxt 5 stops importing h3 - #24283

Open
s1gr1d wants to merge 2 commits into
developfrom
t3code/9c33bc1e
Open

fix(nuxt): Split the Nitro error hook as Nuxt 5 stops importing h3#24283
s1gr1d wants to merge 2 commits into
developfrom
t3code/9c33bc1e

Conversation

@s1gr1d

@s1gr1d s1gr1d commented Sep 10, 2026

Copy link
Copy Markdown
Member

Nuxt 5 switched on its Nitro v2 compatibility layer for any module whose server code imports h3: nuxt/nuxt#36318

Split it the way we already split storage and database: captureErrorHook uses nitro/h3, captureErrorHook-legacy keeps h3, and module.ts picks by Nitro major.

Our CI tests currently show this warning:

[WebServer] [warn] [NUXT_B9003] Nitro v2 compatibility was applied to server code from 1 module, because of what it imports:
[WebServer]   - `@sentry/nuxt/module` (imports `h3`)
[WebServer] ╰▶ fix: This layer is transitional and will be removed in Nuxt 6. Update the module to import from `nuxt/server`, registering the portable file alongside the one it ships today, or report it to the module author if the module is not your own.

@github-actions

github-actions Bot commented Sep 10, 2026

Copy link
Copy Markdown
Contributor

size-limit report 📦

Path Size % Change Change
@sentry/browser 28.91 kB +0.39% +110 B 🔺
@sentry/browser - with treeshaking flags 27.21 kB +0.37% +100 B 🔺
@sentry/browser - with treeshaking flags tracing without tracing 27.1 kB +0.35% +93 B 🔺
@sentry/browser (incl. Tracing) 50.27 kB +2.15% +1.05 kB 🔺
@sentry/browser (incl. Tracing + Span Streaming) 50.28 kB +2.15% +1.06 kB 🔺
@sentry/browser (incl. Tracing, Profiling) 53.26 kB +2.18% +1.13 kB 🔺
@sentry/browser (incl. Tracing, Replay) 89.76 kB +1.13% +998 B 🔺
@sentry/browser (incl. Tracing, Replay) - with treeshaking flags 78.86 kB +1.16% +901 B 🔺
@sentry/browser (incl. Tracing, Replay with Canvas) 94.45 kB +1.08% +1.01 kB 🔺
@sentry/browser (incl. Tracing, Replay, Feedback) 107.46 kB +1.02% +1.08 kB 🔺
@sentry/browser (incl. Feedback) 46.4 kB +0.23% +106 B 🔺
@sentry/browser (incl. sendFeedback) 33.96 kB +0.29% +96 B 🔺
@sentry/browser (incl. FeedbackAsync) 39.07 kB +0.24% +93 B 🔺
@sentry/browser (incl. Metrics) 29.93 kB +0.36% +105 B 🔺
@sentry/browser (incl. Logs) 30.19 kB +0.34% +101 B 🔺
@sentry/browser (incl. Metrics & Logs) 30.86 kB +0.37% +112 B 🔺
@sentry/react 30.66 kB +0.37% +113 B 🔺
@sentry/react (incl. Tracing) 52.59 kB +2.01% +1.03 kB 🔺
@sentry/vue 36.15 kB +0.28% +99 B 🔺
@sentry/vue (incl. Tracing) 52.53 kB +2.05% +1.05 kB 🔺
@sentry/svelte 28.93 kB +0.32% +91 B 🔺
CDN Bundle 30.64 kB +0.32% +95 B 🔺
CDN Bundle (incl. Tracing) 50.78 kB +2.1% +1.04 kB 🔺
CDN Bundle (incl. Logs, Metrics) 32.92 kB +0.32% +102 B 🔺
CDN Bundle (incl. Tracing, Logs, Metrics) 52.73 kB +2% +1.03 kB 🔺
CDN Bundle (incl. Replay, Logs, Metrics) 73.61 kB +0.19% +135 B 🔺
CDN Bundle (incl. Tracing, Replay) 88.32 kB +1.19% +1.03 kB 🔺
CDN Bundle (incl. Tracing, Replay, Logs, Metrics) 90.29 kB +1.24% +1.1 kB 🔺
CDN Bundle (incl. Tracing, Replay, Feedback) 94.36 kB +1.23% +1.15 kB 🔺
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics) 96.38 kB +1.23% +1.17 kB 🔺
CDN Bundle - uncompressed 90.72 kB +0.29% +257 B 🔺
CDN Bundle (incl. Tracing) - uncompressed 151.68 kB +2.37% +3.51 kB 🔺
CDN Bundle (incl. Logs, Metrics) - uncompressed 97.3 kB +0.28% +266 B 🔺
CDN Bundle (incl. Tracing, Logs, Metrics) - uncompressed 157.64 kB +2.28% +3.51 kB 🔺
CDN Bundle (incl. Replay, Logs, Metrics) - uncompressed 226.71 kB +0.19% +417 B 🔺
CDN Bundle (incl. Tracing, Replay) - uncompressed 271.25 kB +1.31% +3.49 kB 🔺
CDN Bundle (incl. Tracing, Replay, Logs, Metrics) - uncompressed 277.2 kB +1.28% +3.49 kB 🔺
CDN Bundle (incl. Tracing, Replay, Feedback) - uncompressed 284.95 kB +1.24% +3.49 kB 🔺
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics) - uncompressed 290.89 kB +1.22% +3.49 kB 🔺
@sentry/nextjs (client) 54.91 kB +1.7% +913 B 🔺
@sentry/sveltekit (client) 50.69 kB +2.1% +1.04 kB 🔺
@sentry/core/server 37.08 kB +0.26% +96 B 🔺
@sentry/core/browser 13.66 kB +0.82% +110 B 🔺
@sentry/node 128.42 kB +0.5% +631 B 🔺
@sentry/node/import (ESM hook with diagnostics-channel injection) 81.82 kB +0.26% +205 B 🔺
@sentry/node - without tracing 89.02 kB +0.35% +310 B 🔺
@sentry/node - without channel injection 107.53 kB +0.47% +501 B 🔺
@sentry/aws-serverless 97.41 kB +0.33% +311 B 🔺
@sentry/cloudflare (withSentry) - minified 203.01 kB +0.52% +1.03 kB 🔺
@sentry/cloudflare (withSentry) 505.44 kB +0.55% +2.76 kB 🔺

View base workflow run

@s1gr1d

s1gr1d commented Sep 10, 2026

Copy link
Copy Markdown
Member Author

This still fails, but because of another issue.

Cannot find module 'ofetch' imported from 'virtual:nuxt:.nuxt%2Ffetch.server.mjs'
  at fetchModule (vite@8.2.2/dist/node/chunks/node.js:34330:32)
  at FetchableDevEnvironment.fetchModule (nitro@3.0.260903-beta/dist/_build/vite.dev.mjs:51:17)

That's probably an upstream issue.
It's Nitro's dev Vite environment failing to resolve a bare ofetch from a virtual module, under pnpm isolation where ofetch only exists as a transitive dep of nuxt.

Created a PR to add ofetch as explicit dependency for now: #24304

s1gr1d added a commit that referenced this pull request Sep 10, 2026
@s1gr1d
s1gr1d marked this pull request as ready for review September 10, 2026 13:56
@s1gr1d
s1gr1d requested a review from a team as a code owner September 10, 2026 13:56
@s1gr1d
s1gr1d requested review from mydea and nicohrubec and removed request for a team September 10, 2026 13:56
Comment on lines +51 to +58
const { method, path } = {
method: errorContext.event?._method ? errorContext.event._method : '',
path: errorContext.event?._path ? errorContext.event._path : null,
};

if (path) {
getCurrentScope().setTransactionName(`${method} ${path}`);
}

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: The createCaptureErrorHook utility accesses event._method and event._path, which are internal to h3 v1. These fields do not exist in h3 v2 (used by Nitro v3/Nuxt 5+).
Severity: MEDIUM

Suggested Fix

Update the shared utility to handle both h3 v1 and h3 v2 event shapes. Check for the standard event.path before falling back to event._path, and use event.req.method or event.method to get the request method, ensuring compatibility with both Nitro v2 and v3.

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/nuxt/src/runtime/utils/captureError.ts#L51-L58

Potential issue: The shared utility `createCaptureErrorHook` attempts to set the Sentry
transaction name by accessing `errorContext.event._method` and
`errorContext.event._path`. These properties are internal to the `H3Event` from `h3 v1`
(used in Nuxt 3/4). However, in Nuxt 5+ which uses Nitro v3 and `h3 v2`, the event
object is an `HTTPEvent` and lacks these underscore-prefixed fields. Consequently, for
Nuxt 5+ applications, the method and path will be `undefined`, the
`setTransactionName()` function will not be called, and transaction names for captured
server errors will be missing, degrading observability.

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

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.

1 participant