Repository: vercel/next.js
Pull request: add debug logs to onSegmentPrerenderError

Adds logs to collectSegmentError when verbose logging is enabled to help identify errors that occur during this phase. 

Changed files:
filename: packages/next/errors.json
patch: @@ -946,5 +946,6 @@
   "945": "createNodeStreamFromChunks cannot be used in the edge runtime",
   "946": "Failed to deserialize errors.",
   "947": "Expected `sendErrorsToBrowser` to be defined in renderOpts.",
-  "948": "Failed to serialize errors."
+  "948": "Failed to serialize errors.",
+  "949": "Route %s errored during %s. These errors are normally ignored and may not prevent the route from prerendering but are logged here because build debugging is enabled.\n          \nOriginal Error: %s"
 }

filename: packages/next/src/server/app-render/app-render.tsx
patch: @@ -170,7 +170,10 @@ import {
   createReactServerPrerenderResultFromRender,
   prerenderAndAbortInSequentialTasks,
 } from './app-render-prerender-utils'
-import { printDebugThrownValueForProspectiveRender } from './prospective-render-utils'
+import {
+  Phase,
+  printDebugThrownValueForProspectiveRender,
+} from './prospective-render-utils'
 import {
   pipelineInSequentialTasks,
   scheduleInSequentialTasks,
@@ -1073,7 +1076,11 @@ async function prospectiveRuntimeServerPrerender(
           process.env.NEXT_DEBUG_BUILD ||
           process.env.__NEXT_VERBOSE_LOGGING
         ) {
-          printDebugThrownValueForProspectiveRender(err, workStore.route)
+          printDebugThrownValueForProspectiveRender(
+            err,
+            workStore.route,
+            Phase.ProspectiveRender
+          )
         }
       },
       // We don't want to stop rendering until the cacheSignal is complete so we pass
@@ -1110,7 +1117,11 @@ async function prospectiveRuntimeServerPrerender(
     ) {
       // We don't normally log these errors because we are going to retry anyway but
       // it can be useful for debugging Next.js itself to get visibility here when needed
-      printDebugThrownValueForProspectiveRender(err, workStore.route)
+      printDebugThrownValueForProspectiveRender(
+        err,
+        workStore.route,
+        Phase.ProspectiveRender
+      )
     }
     return null
   }
@@ -3832,7 +3843,11 @@ async function warmupModuleCacheForRuntimeValidationInDev(
         ) {
           // We don't normally log these errors because we are going to retry anyway but
           // it can be useful for debugging Next.js itself to get visibility here when needed
-          printDebugThrownValueForProspectiveRender(err, workStore.route)
+          printDebugThrownValueForProspectiveRender(
+            err,
+            workStore.route,
+            Phase.ProspectiveRender
+          )
         }
       },
       // We don't need bootstrap scripts in this prerender
@@ -3863,7 +3878,11 @@ async function warmupModuleCacheForRuntimeValidationInDev(
     ) {
       // We don't normally log these errors because we are going to retry anyway but
       // it can be useful for debugging Next.js itself to get visibility here when needed
-      printDebugThrownValueForProspectiveRender(err, workStore.route)
+      printDebugThrownValueForProspectiveRender(
+        err,
+        workStore.route,
+        Phase.ProspectiveRender
+      )
     }
   })
 
@@ -4350,7 +4369,11 @@ async function prerenderToStream(
               process.env.NEXT_DEBUG_BUILD ||
               process.env.__NEXT_VERBOSE_LOGGING
             ) {
-              printDebugThrownValueForProspectiveRender(err, workStore.route)
+              printDebugThrownValueForProspectiveRender(
+                err,
+                workStore.route,
+                Phase.ProspectiveRender
+              )
             }
           },
           // We don't want to stop rendering until the cacheSignal is complete so we pass
@@ -4402,7 +4425,11 @@ async function prerenderToStream(
         ) {
           // We don't normally log these errors because we are going to retry anyway but
           // it can be useful for debugging Next.js itself to get visibility here when needed
-          printDebugThrownValueForProspectiveRender(err, workStore.route)
+          printDebugThrownValueForProspectiveRender(
+            err,
+            workStore.route,
+            Phase.ProspectiveRender
+          )
         }
       }
 
@@ -4473,7 +4500,11 @@ async function prerenderToStream(
               ) {
                 // We don't normally log these errors because we are going to retry anyway but
                 // it can be useful for debugging Next.js itself to get visibility here when needed
-                printDebugThrownValueForProspectiveRender(err, workStore.route)
+                printDebugThrownValueForProspectiveRender(
+                  err,
+                  workStore.route,
+                  Phase.ProspectiveRender
+                )
               }
             },
             bootstrapScripts: [bootstrapScript],
@@ -4503,7 +4534,11 @@ async function prerenderToStream(
           ) {
             // We don't normally log these errors because we are going to retry anyway but
             // it can be useful for debugging Next.js itself to get visibility here when needed
-            printDebugThrownValueForProspectiveRender(err, workStore.route)
+            printDebugThrownValueForProspectiveRender(
+              err,
+              workStore.route,
+              Phase.ProspectiveRender
+            )
           }
         })
 

filename: packages/next/src/server/app-render/collect-segment-data.tsx
patch: @@ -27,6 +27,11 @@ import {
   HEAD_REQUEST_KEY,
 } from '../../shared/lib/segment-cache/segment-value-encoding'
 import { getDigestForWellKnownError } from './create-error-handler'
+import {
+  Phase,
+  printDebugThrownValueForProspectiveRender,
+} from './prospective-render-utils'
+import { workAsyncStorage } from './work-async-storage.external'
 
 // Contains metadata about the route tree. The client must fetch this before
 // it can fetch any actual segment data.
@@ -85,6 +90,14 @@ function onSegmentPrerenderError(error: unknown) {
   }
   // We don't need to log the errors because we would have already done that
   // when generating the original Flight stream for the whole page.
+  if (process.env.NEXT_DEBUG_BUILD || process.env.__NEXT_VERBOSE_LOGGING) {
+    const workStore = workAsyncStorage.getStore()
+    printDebugThrownValueForProspectiveRender(
+      error,
+      workStore?.route ?? 'unknown route',
+      Phase.SegmentCollection
+    )
+  }
 }
 
 export async function collectSegmentData(

filename: packages/next/src/server/app-render/prospective-render-utils.ts
patch: @@ -1,9 +1,15 @@
 import { getDigestForWellKnownError } from './create-error-handler'
 import { isReactLargeShellError } from './react-large-shell-error'
 
+export enum Phase {
+  ProspectiveRender = 'the prospective render',
+  SegmentCollection = 'segment collection',
+}
+
 export function printDebugThrownValueForProspectiveRender(
   thrownValue: unknown,
-  route: string
+  route: string,
+  phase: Phase
 ) {
   // We don't need to print well-known Next.js errors.
   if (getDigestForWellKnownError(thrownValue)) {
@@ -28,7 +34,7 @@ export function printDebugThrownValueForProspectiveRender(
       const stackStart = originalErrorStack.indexOf('\n')
       if (stackStart > -1) {
         const error = new Error(
-          `Route ${route} errored during the prospective render. These errors are normally ignored and may not prevent the route from prerendering but are logged here because build debugging is enabled.
+          `Route ${route} errored during ${phase}. These errors are normally ignored and may not prevent the route from prerendering but are logged here because build debugging is enabled.
           
 Original Error: ${message}`
         )
@@ -43,14 +49,14 @@ Original Error: ${message}`
   }
 
   if (message) {
-    console.error(`Route ${route} errored during the prospective render. These errors are normally ignored and may not prevent the route from prerendering but are logged here because build debugging is enabled. No stack was provided.
+    console.error(`Route ${route} errored during ${phase}. These errors are normally ignored and may not prevent the route from prerendering but are logged here because build debugging is enabled. No stack was provided.
           
 Original Message: ${message}`)
     return
   }
 
   console.error(
-    `Route ${route} errored during the prospective render. These errors are normally ignored and may not prevent the route from prerendering but are logged here because build debugging is enabled. The thrown value is logged just following this message`
+    `Route ${route} errored during ${phase}. These errors are normally ignored and may not prevent the route from prerendering but are logged here because build debugging is enabled. The thrown value is logged just following this message`
   )
   console.error(thrownValue)
   return

filename: packages/next/src/server/route-modules/app-route/module.ts
patch: @@ -31,7 +31,10 @@ import {
 import { HeadersAdapter } from '../../web/spec-extension/adapters/headers'
 import { RequestCookiesAdapter } from '../../web/spec-extension/adapters/request-cookies'
 import { parsedUrlQueryToParams } from './helpers/parsed-url-query-to-params'
-import { printDebugThrownValueForProspectiveRender } from '../../app-render/prospective-render-utils'
+import {
+  Phase,
+  printDebugThrownValueForProspectiveRender,
+} from '../../app-render/prospective-render-utils'
 
 import * as serverHooks from '../../../client/components/hooks-server-context'
 import { DynamicServerError } from '../../../client/components/hooks-server-context'
@@ -432,7 +435,11 @@ export class AppRouteRouteModule extends RouteModule<
               process.env.NEXT_DEBUG_BUILD ||
               process.env.__NEXT_VERBOSE_LOGGING
             ) {
-              printDebugThrownValueForProspectiveRender(err, workStore.route)
+              printDebugThrownValueForProspectiveRender(
+                err,
+                workStore.route,
+                Phase.ProspectiveRender
+              )
             }
           }
           if (
@@ -452,7 +459,8 @@ export class AppRouteRouteModule extends RouteModule<
                 } else if (process.env.NEXT_DEBUG_BUILD) {
                   printDebugThrownValueForProspectiveRender(
                     err,
-                    workStore.route
+                    workStore.route,
+                    Phase.ProspectiveRender
                   )
                 }
               }