Skip to content

Commit 22dc196

Browse files
fix(error-logging): rollup errors weren't displaying id and codeframe (#16540)
1 parent c04192b commit 22dc196

File tree

1 file changed

+47
-6
lines changed

1 file changed

+47
-6
lines changed

packages/vite/src/node/build.ts

+47-6
Original file line numberDiff line numberDiff line change
@@ -545,23 +545,64 @@ export async function build(
545545
},
546546
}
547547

548-
const mergeRollupError = (e: RollupError) => {
548+
/**
549+
* The stack string usually contains a copy of the message at the start of the stack.
550+
* If the stack starts with the message, we remove it and just return the stack trace
551+
* portion. Otherwise the original stack trace is used.
552+
*/
553+
function extractStack(e: RollupError) {
554+
const { stack, name = 'Error', message } = e
555+
556+
// If we don't have a stack, not much we can do.
557+
if (!stack) {
558+
return stack
559+
}
560+
561+
const expectedPrefix = `${name}: ${message}\n`
562+
if (stack.startsWith(expectedPrefix)) {
563+
return stack.slice(expectedPrefix.length)
564+
}
565+
566+
return stack
567+
}
568+
569+
/**
570+
* Esbuild code frames have newlines at the start and end of the frame, rollup doesn't
571+
* This function normalizes the frame to match the esbuild format which has more pleasing padding
572+
*/
573+
const normalizeCodeFrame = (frame: string) => {
574+
const trimmedPadding = frame.replace(/^\n|\n$/g, '')
575+
return `\n${trimmedPadding}\n`
576+
}
577+
578+
const enhanceRollupError = (e: RollupError) => {
579+
const stackOnly = extractStack(e)
580+
549581
let msg = colors.red((e.plugin ? `[${e.plugin}] ` : '') + e.message)
550582
if (e.id) {
551583
msg += `\nfile: ${colors.cyan(
552584
e.id + (e.loc ? `:${e.loc.line}:${e.loc.column}` : ''),
553585
)}`
554586
}
555587
if (e.frame) {
556-
msg += `\n` + colors.yellow(e.frame)
588+
msg += `\n` + colors.yellow(normalizeCodeFrame(e.frame))
589+
}
590+
591+
e.message = msg
592+
593+
// We are rebuilding the stack trace to include the more detailed message at the top.
594+
// Previously this code was relying on mutating e.message changing the generated stack
595+
// when it was accessed, but we don't have any guarantees that the error we are working
596+
// with hasn't already had its stack accessed before we get here.
597+
if (stackOnly !== undefined) {
598+
e.stack = `${e.message}\n${stackOnly}`
557599
}
558-
return msg
559600
}
560601

561602
const outputBuildError = (e: RollupError) => {
562-
const msg = mergeRollupError(e)
603+
enhanceRollupError(e)
563604
clearLine()
564-
config.logger.error(msg, { error: e })
605+
config.logger.error(e.message, { error: e })
565606
}
566607

567608
let bundle: RollupBuild | undefined
@@ -727,7 +768,7 @@ export async function build(
727768
)
728769
return Array.isArray(outputs) ? res : res[0]
729770
} catch (e) {
730-
e.message = mergeRollupError(e)
771+
enhanceRollupError(e)
731772
clearLine()
732773
if (startTime) {
733774
config.logger.error(

0 commit comments

Comments
 (0)