Skip to content

Commit 8f46d31

Browse files
committed
avoid logging stacks for internal errors
1 parent db301b0 commit 8f46d31

File tree

5 files changed

+20
-14
lines changed

5 files changed

+20
-14
lines changed

packages/next/src/export/worker.ts

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ import {
4848
import { needsExperimentalReact } from '../lib/needs-experimental-react'
4949
import { runWithCacheScope } from '../server/async-storage/cache-scope.external'
5050
import type { AppRouteRouteModule } from '../server/route-modules/app-route/module.compiled'
51+
import { isStaticGenBailoutError } from '../client/components/static-generation-bailout'
5152

5253
const envConfig = require('../shared/lib/runtime-config.external')
5354

@@ -433,16 +434,17 @@ export async function exportPages(
433434
if (attempt >= maxAttempts - 1) {
434435
// Log a message if we've reached the maximum number of attempts.
435436
// We only care to do this if maxAttempts was configured.
436-
if (maxAttempts > 0) {
437+
if (maxAttempts > 1) {
437438
console.info(
438439
`Failed to build ${pageKey} after ${maxAttempts} attempts.`
439440
)
440441
}
441442
// If prerenderEarlyExit is enabled, we'll exit the build immediately.
442443
if (nextConfig.experimental.prerenderEarlyExit) {
443-
throw new ExportPageError(
444+
console.error(
444445
`Export encountered an error on ${pageKey}, exiting the build.`
445446
)
447+
process.exit(1)
446448
} else {
447449
// Otherwise, this is a no-op. The build will continue, and a summary of failed pages will be displayed at the end.
448450
}
@@ -540,8 +542,21 @@ async function exportPage(
540542
`\nError occurred prerendering page "${input.path}". Read more: https://nextjs.org/docs/messages/prerender-error\n`
541543
)
542544

545+
// bailoutToCSRError errors should not leak to the user as they are not actionable; they're
546+
// a framework signal
543547
if (!isBailoutToCSRError(err)) {
544-
console.error(isError(err) && err.stack ? err.stack : err)
548+
// A static generation bailout error is a framework signal to fail static generation but
549+
// and will encode a reason in the error message. If there is a message, we'll print it.
550+
// Otherwise there's nothing to show as we don't want to leak an error internal error stack to the user.
551+
if (isStaticGenBailoutError(err)) {
552+
if (err.message) {
553+
console.error(err.message)
554+
}
555+
} else if (isError(err) && err.stack) {
556+
console.error(err.stack)
557+
} else {
558+
console.error(err)
559+
}
545560
}
546561

547562
return { error: true, duration: Date.now() - start, files: [] }

packages/next/src/server/app-render/dynamic-rendering.ts

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -653,9 +653,7 @@ export function throwIfDisallowedDynamic(
653653
console.error(syncError)
654654
}
655655
// The actual error should have been logged when the sync access ocurred
656-
throw new StaticGenBailoutError(
657-
`Route "${route}" could not be prerendered.`
658-
)
656+
throw new StaticGenBailoutError()
659657
}
660658

661659
const dynamicErrors = dynamicValidation.dynamicErrors
@@ -664,9 +662,7 @@ export function throwIfDisallowedDynamic(
664662
console.error(dynamicErrors[i])
665663
}
666664

667-
throw new StaticGenBailoutError(
668-
`Route "${route}" could not be prerendered.`
669-
)
665+
throw new StaticGenBailoutError()
670666
}
671667

672668
if (!dynamicValidation.hasSuspendedDynamic) {

test/e2e/app-dir/dynamic-io-errors/dynamic-io-errors.platform-dynamic.test.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,6 @@ function runTests(options: { withMinification: boolean }) {
126126
'Error: Route "/" used `Math.random()` outside of `"use cache"` and without explicitly calling `await connection()` beforehand. See more info here: https://nextjs.org/docs/messages/next-prerender-random'
127127
)
128128
expectError('Error occurred prerendering page "/"')
129-
expectError('Error: Route "/" could not be prerendered.')
130129
expectError('exiting the build.')
131130
})
132131
})

test/e2e/app-dir/dynamic-io-errors/dynamic-io-errors.sync-dynamic.test.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,6 @@ function runTests(options: { withMinification: boolean }) {
124124

125125
expectError('Route "/" used `searchParams.foo`')
126126
expectError('Error occurred prerendering page "/"')
127-
expectError('Error: Route "/" could not be prerendered.')
128127
expectError('exiting the build.')
129128
})
130129
})
@@ -212,7 +211,6 @@ function runTests(options: { withMinification: boolean }) {
212211

213212
expectError('Route "/" used `searchParams.foo`')
214213
expectError('Error occurred prerendering page "/"')
215-
expectError('Error: Route "/" could not be prerendered.')
216214
expectError('exiting the build.')
217215
})
218216
})
@@ -300,7 +298,6 @@ function runTests(options: { withMinification: boolean }) {
300298

301299
expectError('Route "/" used `cookies().get(\'token\')`')
302300
expectError('Error occurred prerendering page "/"')
303-
expectError('Route "/" could not be prerendered.')
304301
expectError('exiting the build.')
305302
})
306303
})

test/e2e/app-dir/dynamic-io-errors/dynamic-io-errors.test.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,6 @@ function runTests(options: { withMinification: boolean }) {
337337
)
338338
}
339339
expectError('Error occurred prerendering page "/"')
340-
expectError('Error: Route "/" could not be prerendered.')
341340
expectError('exiting the build.')
342341
})
343342
})

0 commit comments

Comments
 (0)