@@ -42,17 +42,42 @@ func CatchVectorizedRuntimeError(operation func()) (retErr error) {
42
42
// StorageError was caused by something below SQL, and represents an error
43
43
// that we'd simply like to propagate along.
44
44
var se * StorageError
45
- // notInternalError is an error that will be returned to the client
46
- // without a stacktrace, sentry report, or "internal error" designation .
45
+ // notInternalError is an error from the vectorized engine that we'd
46
+ // simply like to propagate along .
47
47
var nie * notInternalError
48
- if errors .As (err , & se ) || errors .As (err , & nie ) {
48
+ // internalError is an error from the vectorized engine that might need to
49
+ // be returned to the client with a stacktrace, sentry report, and
50
+ // "internal error" designation.
51
+ var ie * internalError
52
+ passthrough := errors .As (err , & se ) || errors .As (err , & nie )
53
+ if errors .As (err , & ie ) {
54
+ // Unwrap so that internalError doesn't show up in sentry reports.
55
+ retErr = ie .Unwrap ()
56
+ // If the internal error doesn't already have an error code, mark it as
57
+ // an assertion error so that we generate a sentry report. (We don't do
58
+ // this for StorageError, notInternalError, or context.Canceled to avoid
59
+ // creating unnecessary sentry reports.)
60
+ if ! passthrough && ! errors .Is (retErr , context .Canceled ) {
61
+ if code := pgerror .GetPGCode (retErr ); code == pgcode .Uncategorized {
62
+ retErr = errors .NewAssertionErrorWithWrappedErrf (
63
+ retErr , "unexpected error from the vectorized engine" ,
64
+ )
65
+ }
66
+ }
67
+ return
68
+ }
69
+ if passthrough {
49
70
retErr = err
50
71
return
51
72
}
52
73
}
53
74
54
- // Find where the panic came from and only proceed if it is related to the
55
- // vectorized engine.
75
+ // For other types of errors, we need to check where the panic came from. We
76
+ // only want to recover from panics that originated within the vectorized
77
+ // engine. We treat a panic from lower in the stack as unrecoverable.
78
+
79
+ // Find where the panic came from and only proceed if it
80
+ // is related to the vectorized engine.
56
81
stackTrace := string (debug .Stack ())
57
82
scanner := bufio .NewScanner (strings .NewReader (stackTrace ))
58
83
panicLineFound := false
@@ -193,16 +218,41 @@ func decodeNotInternalError(
193
218
return newNotInternalError (cause )
194
219
}
195
220
221
+ // internalError is an error that occurs because the vectorized engine is in an
222
+ // unexpected state. Usually it wraps an assertion error.
223
+ type internalError struct {
224
+ cause error
225
+ }
226
+
227
+ func newInternalError (err error ) * internalError {
228
+ return & internalError {cause : err }
229
+ }
230
+
231
+ var (
232
+ _ errors.Wrapper = & internalError {}
233
+ )
234
+
235
+ func (e * internalError ) Error () string { return e .cause .Error () }
236
+ func (e * internalError ) Cause () error { return e .cause }
237
+ func (e * internalError ) Unwrap () error { return e .Cause () }
238
+
239
+ func decodeInternalError (
240
+ _ context.Context , cause error , _ string , _ []string , _ proto.Message ,
241
+ ) error {
242
+ return newInternalError (cause )
243
+ }
244
+
196
245
func init () {
197
246
errors .RegisterWrapperDecoder (errors .GetTypeKey ((* notInternalError )(nil )), decodeNotInternalError )
247
+ errors .RegisterWrapperDecoder (errors .GetTypeKey ((* internalError )(nil )), decodeInternalError )
198
248
}
199
249
200
- // InternalError simply panics with the provided object . It will always be
201
- // caught and returned as internal error to the client with the corresponding
250
+ // InternalError panics with the error wrapped by internalError . It will always
251
+ // be caught and returned as internal error to the client with the corresponding
202
252
// stack trace. This method should be called to propagate errors that resulted
203
253
// in the vectorized engine being in an *unexpected* state.
204
254
func InternalError (err error ) {
205
- panic (err )
255
+ panic (newInternalError ( err ) )
206
256
}
207
257
208
258
// ExpectedError panics with the error that is wrapped by
0 commit comments