1
+ import type { ErrorInfo } from 'react'
2
+
1
3
import stringHash from 'next/dist/compiled/string-hash'
2
4
import { formatServerError } from '../../lib/format-server-error'
3
5
import { SpanStatusCode , getTracer } from '../lib/trace/tracer'
@@ -10,27 +12,24 @@ declare global {
10
12
var __next_log_error__ : undefined | ( ( err : unknown ) => void )
11
13
}
12
14
13
- type ErrorHandler = ( err : unknown , errorInfo ?: unknown ) => string | undefined
15
+ type RSCErrorHandler = ( err : unknown ) => string | undefined
16
+ type SSRErrorHandler = (
17
+ err : unknown ,
18
+ errorInfo ?: ErrorInfo
19
+ ) => string | undefined
14
20
15
21
export type DigestedError = Error & { digest : string }
16
22
17
23
export function createFlightReactServerErrorHandler (
18
24
dev : boolean ,
19
25
onReactServerRenderError : ( err : any ) => void
20
- ) : ErrorHandler {
21
- return ( err : any , errorInfo ?: unknown ) => {
26
+ ) : RSCErrorHandler {
27
+ return ( err : any ) => {
22
28
// If the error already has a digest, respect the original digest,
23
29
// so it won't get re-generated into another new error.
24
30
if ( ! err . digest ) {
25
31
// TODO-APP: look at using webcrypto instead. Requires a promise to be awaited.
26
- err . digest = stringHash (
27
- err . message +
28
- ( typeof errorInfo === 'object' &&
29
- errorInfo !== null &&
30
- 'stack' in errorInfo
31
- ? errorInfo . stack
32
- : err . stack || '' )
33
- ) . toString ( )
32
+ err . digest = stringHash ( err . message + err . stack || '' ) . toString ( )
34
33
}
35
34
36
35
// If the response was closed, we don't need to log the error.
@@ -75,15 +74,13 @@ export function createHTMLReactServerErrorHandler(
75
74
reactServerErrors : Map < string , DigestedError > ,
76
75
silenceLogger : boolean ,
77
76
onReactServerRenderError : undefined | ( ( err : any ) => void )
78
- ) : ErrorHandler {
79
- return ( err : any , errorInfo : any ) => {
77
+ ) : RSCErrorHandler {
78
+ return ( err : any ) => {
80
79
// If the error already has a digest, respect the original digest,
81
80
// so it won't get re-generated into another new error.
82
81
if ( ! err . digest ) {
83
82
// TODO-APP: look at using webcrypto instead. Requires a promise to be awaited.
84
- err . digest = stringHash (
85
- err . message + ( errorInfo ?. stack || err . stack || '' )
86
- ) . toString ( )
83
+ err . digest = stringHash ( err . message + ( err . stack || '' ) ) . toString ( )
87
84
}
88
85
89
86
// If the response was closed, we don't need to log the error.
@@ -146,9 +143,9 @@ export function createHTMLErrorHandler(
146
143
reactServerErrors : Map < string , DigestedError > ,
147
144
allCapturedErrors : Array < unknown > ,
148
145
silenceLogger : boolean ,
149
- onHTMLRenderSSRError : ( err : any ) => void
150
- ) : ErrorHandler {
151
- return ( err : any , errorInfo : any ) => {
146
+ onHTMLRenderSSRError : ( err : any , errorInfo ?: ErrorInfo ) => void
147
+ ) : SSRErrorHandler {
148
+ return ( err : any , errorInfo ?: ErrorInfo ) => {
152
149
let isSSRError = true
153
150
154
151
// If the error already has a digest, respect the original digest,
@@ -165,7 +162,10 @@ export function createHTMLErrorHandler(
165
162
}
166
163
} else {
167
164
err . digest = stringHash (
168
- err . message + ( errorInfo ?. stack || err . stack || '' )
165
+ err . message +
166
+ ( typeof ( errorInfo as any ) ?. stack === 'string'
167
+ ? ( errorInfo as any ) . stack
168
+ : err . stack || '' )
169
169
) . toString ( )
170
170
}
171
171
@@ -215,7 +215,7 @@ export function createHTMLErrorHandler(
215
215
// HTML errors contain RSC errors as well, filter them out before reporting
216
216
isSSRError
217
217
) {
218
- onHTMLRenderSSRError ( err )
218
+ onHTMLRenderSSRError ( err , errorInfo )
219
219
}
220
220
}
221
221
0 commit comments