-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Nuxt/Vue: error 500 when exception captured #72696 #12515
Comments
Assigning to @getsentry/support for routing ⏲️ |
Hi @saint-james-fr, could you share a minimal reproduction of this error happening? Thanks! |
Hi @AbhiPrasad, here it is: https://github.com/saint-james-fr/sentry-error Simple nuxt app created with Then I pinned the same versions of packages mentioned in my earlier post. And i've got the same result: |
@saint-james-fr This seems to work as intended. You are not handling the error so it leads to an error state. Sentry should still capture the error, but you have to code some fallback UI for these error states. I recommend taking a look at Nuxt's error handling docs. |
Hi @AbhiPrasad thanks for checking this out, I'll try this but without Sentry, it just logged an error in the console, it does not crash like this just so you know. |
it happened to my project too. when sentry is capturing errors and an error occurs, the application crashes completely. while without sentry the project continue to work normally |
My workaround to fix this issue. of course you need to copy the utils from
|
I lack context into how Nuxt works, but I assume you all followed https://www.lichter.io/articles/nuxt3-sentry-recipe as a guide? We're working on a proper Nuxt SDK here: #9095, that should make this experience a lot better. maybe @manniL do you have any context about why adding Sentry via |
have seen this based on manniL/nuxt3-sentry-recipe#8 but had no time to investigate. Shouldn't happen with v7 though. |
Hey, thanks for checking, indeed I followed these steps @AbhiPrasad. |
Are there any updates on this? Same here, without Sentry, the error is displayed in the console but without crashing the app. |
Same here. This issue prevents us from using the Nuxt module. |
I will take a look at this! In the meantime, please take a look at Nuxt Error Handling to capture unhandled errors. |
Could Confirm that the error is only happening on Folder structure (inside
index.ts (Module entry) import { addPlugin, addServerPlugin, addVitePlugin, createResolver, defineNuxtModule, extendViteConfig, useRuntimeConfig } from "@nuxt/kit"
import { sentryVitePlugin } from "@sentry/vite-plugin"
export default defineNuxtModule({
meta: {
name: "nuxt-sentry",
configKey: "sentry",
},
async setup() {
const resolver = createResolver(import.meta.url)
const config = useRuntimeConfig()
const isProd = import.meta.env.NODE_ENV === "production"
if (!isProd) {
console.warn("Not in Production, Disabling Sentry")
return
}
addPlugin({
src: resolver.resolve("runtime/plugin.client"),
mode: "client",
})
addServerPlugin(resolver.resolve("runtime/plugin.server"))
extendViteConfig((config) => {
config.build ??= {}
config.build.sourcemap = true
})
addVitePlugin(
sentryVitePlugin({
org: config.sentry.organization,
project: config.sentry.project,
authToken: config.sentry.token,
}),
)
},
}) plugin.client.ts (Thanks to @falfituri) import { browserTracingIntegration, captureException, init, replayIntegration } from "@sentry/vue"
import { formatComponentName, generateComponentTrace } from "./utils"
export default defineNuxtPlugin((nuxtApp) => {
const router = useRouter()
const config = useRuntimeConfig()
if (!config.public.sentry.dsn) {
console.warn("Sentry DSN not set, skipping Sentry initialization")
return
}
init({
app: nuxtApp.vueApp,
dsn: config.public.sentry.dsn,
integrations: [
browserTracingIntegration({ router }),
replayIntegration({
maskAllText: false,
blockAllMedia: false,
}),
],
tracesSampleRate: 0.2,
replaysSessionSampleRate: 1.0,
replaysOnErrorSampleRate: 1.0,
})
nuxtApp.vueApp.config.errorHandler = undefined
nuxtApp.hook("vue:error", (error, vm, lifecycleHook) => {
const componentName = formatComponentName(vm, false)
const trace = vm ? generateComponentTrace(vm) : ""
const metadata = { componentName, lifecycleHook, trace }
// @ts-expect-error Sentry Error
metadata.propsData = vm.$props
setTimeout(() => {
captureException(error, {
captureContext: { contexts: { vue: metadata } },
mechanism: { handled: false },
})
})
})
}) plugin.server.ts: import { captureException, init } from "@sentry/node"
import { nodeProfilingIntegration } from "@sentry/profiling-node"
export default defineNitroPlugin((nitroApp) => {
const config = useRuntimeConfig()
if (!config.public.sentry.dsn) {
console.warn("Sentry DSN not set, skipping Sentry initialization")
return
}
init({
dsn: config.public.sentry.dsn,
integrations: [
nodeProfilingIntegration(),
],
tracesSampleRate: 1.0,
profilesSampleRate: 1.0,
})
nitroApp.hooks.hook("error", (error) => {
captureException(error)
})
})
import type { ComponentPublicInstance } from "vue"
const classifyRE = /(?:^|[-_])(\w)/g
const classify = (str: string): string => str.replace(classifyRE, c => c.toUpperCase()).replace(/[-_]/g, "")
const ROOT_COMPONENT_NAME = "<Root>"
const ANONYMOUS_COMPONENT_NAME = "<Anonymous>"
function repeat(str: string, n: number): string {
return str.repeat(n)
}
export function formatComponentName(vm: ComponentPublicInstance | null, includeFile?: boolean): string {
if (!vm) {
return ANONYMOUS_COMPONENT_NAME
}
if (vm.$root === vm) {
return ROOT_COMPONENT_NAME
}
if (!vm.$options) {
return ANONYMOUS_COMPONENT_NAME
}
const options = vm.$options
let name = options.name || options._componentTag || options.__name
const file = options.__file
if (!name && file) {
const match = file.match(/([^/\\]+)\.vue$/)
if (match) {
name = match[1]
}
}
return (
(name ? `<${classify(name)}>` : ANONYMOUS_COMPONENT_NAME) + (file && includeFile !== false ? ` at ${file}` : "")
)
}
export function generateComponentTrace(vm: ComponentPublicInstance | null): string {
// @ts-expect-error Sentry Error
if (vm && (vm._isVue || vm.__isVue) && vm.$parent) {
const tree = []
let currentRecursiveSequence = 0
while (vm) {
if (tree.length > 0) {
const last = tree[tree.length - 1] as any
if (last.constructor === vm.constructor) {
currentRecursiveSequence++
vm = vm.$parent
continue
}
else if (currentRecursiveSequence > 0) {
tree[tree.length - 1] = [last, currentRecursiveSequence]
currentRecursiveSequence = 0
}
}
tree.push(vm)
vm = vm.$parent
}
const formattedTree = tree
.map(
(vm, i) =>
`${
(i === 0 ? "---> " : repeat(" ", 5 + i * 2))
+ (Array.isArray(vm)
? `${formatComponentName(vm[0])}... (${vm[1]} recursive calls)`
: formatComponentName(vm))
}`,
)
.join("\n")
return `\n\nfound in\n\n${formattedTree}`
}
return `\n\n(found in ${formatComponentName(vm)})`
} |
I used your "index.ts (Module entry)" code, but I got an error of |
@Dylan0916 Are you using the latest version of the Nuxt SDK? (btw it is still in alpha, but we are always happy for feedback) The How does your setup look like? Feel free to open an issue regarding |
same here server/sentry.ts export default defineNitroPlugin((nitroApp) => {
const { public: { sentry } } = useRuntimeConfig()
if (!sentry.dsn) {
console.warn('Sentry DSN not set, skipping Sentry initialization')
return
}
// Initialize Sentry
Sentry.init({
dsn: sentry.dsn,
integrations: [nodeProfilingIntegration()],
tracesSampleRate: 1.0,
profilesSampleRate: 1.0
})
nitroApp.hooks.hook('request', (event) => {
event.context.$sentry = Sentry
})
nitroApp.hooks.hookOnce('close', async () => {
await Sentry.close(2000)
})
nitroApp.hooks.hook('error', (error) => {
Sentry.captureException(error)
})
}) pages/example.vue if (!data.value) {
throw new Error("Not found");
} sentry was not capture this error |
@suleyman are you using |
no, im using |
The cause of this issue lies in the initialization behavior of the client-side code of Nuxt and sentry/vue.
The workaround provided here seems to be functioning to suppress the behavior in step 2. |
@konkarin Good debugging! 🔎 This is what I found last week as well :) Nuxt is un-setting their own error handler after the page setup if it wasn't overwritten.
The Sentry SDK however should not re-use the Nuxt |
A PR closing this issue has just been released 🚀This issue was closed by PR #13748, which was included in the 8.32.0 release. |
Environment
SaaS (https://sentry.io/)
Steps to Reproduce
Dependencies:
"@sentry/vue": "8.7.0"
"nuxt": "3.11.2"
"h3": "1.11.1",
...
This is my Nuxt/Vue config inside
plugins/sentry.ts
I run a single vue component
Expected Result
It should capture the error and don't crash the app.
Actual Result
The app crashed with a 500 error (even if it happens on front-end side only)
Product Area
Unknown
Link
No response
DSN
No response
Version
No response
The text was updated successfully, but these errors were encountered: