@@ -13,6 +13,8 @@ import { promiseForObject } from '../jsutils/promiseForObject';
13
13
import type { PromiseOrValue } from '../jsutils/PromiseOrValue' ;
14
14
import { promiseReduce } from '../jsutils/promiseReduce' ;
15
15
16
+ import type { GraphQLErrorBehavior } from '../error/ErrorBehavior' ;
17
+ import { isErrorBehavior } from '../error/ErrorBehavior' ;
16
18
import type { GraphQLFormattedError } from '../error/GraphQLError' ;
17
19
import { GraphQLError } from '../error/GraphQLError' ;
18
20
import { locatedError } from '../error/locatedError' ;
@@ -115,6 +117,7 @@ export interface ExecutionContext {
115
117
typeResolver : GraphQLTypeResolver < any , any > ;
116
118
subscribeFieldResolver : GraphQLFieldResolver < any , any > ;
117
119
errors : Array < GraphQLError > ;
120
+ errorBehavior : GraphQLErrorBehavior ;
118
121
}
119
122
120
123
/**
@@ -130,6 +133,7 @@ export interface ExecutionResult<
130
133
> {
131
134
errors ?: ReadonlyArray < GraphQLError > ;
132
135
data ?: TData | null ;
136
+ onError ?: GraphQLErrorBehavior ;
133
137
extensions ?: TExtensions ;
134
138
}
135
139
@@ -152,6 +156,15 @@ export interface ExecutionArgs {
152
156
fieldResolver ?: Maybe < GraphQLFieldResolver < any , any > > ;
153
157
typeResolver ?: Maybe < GraphQLTypeResolver < any , any > > ;
154
158
subscribeFieldResolver ?: Maybe < GraphQLFieldResolver < any , any > > ;
159
+ /**
160
+ * Experimental. Set to NO_PROPAGATE to prevent error propagation. Set to ABORT to
161
+ * abort a request when any error occurs.
162
+ *
163
+ * Default: PROPAGATE
164
+ *
165
+ * @experimental
166
+ */
167
+ onError ?: GraphQLErrorBehavior ;
155
168
/** Additional execution options. */
156
169
options ?: {
157
170
/** Set the maximum number of errors allowed for coercing (defaults to 50). */
@@ -291,9 +304,21 @@ export function buildExecutionContext(
291
304
fieldResolver,
292
305
typeResolver,
293
306
subscribeFieldResolver,
307
+ < << << << HEAD
294
308
options,
309
+ = === ===
310
+ onError,
311
+ > >>> >>> f3109c39 ( Implement onError proposal)
295
312
} = args ;
296
313
314
+ if ( onError != null && ! isErrorBehavior ( onError ) ) {
315
+ return [
316
+ new GraphQLError (
317
+ 'Unsupported `onError` value; supported values are `PROPAGATE`, `NO_PROPAGATE` and `ABORT`.' ,
318
+ ) ,
319
+ ] ;
320
+ }
321
+
297
322
let operation : OperationDefinitionNode | undefined ;
298
323
const fragments : ObjMap < FragmentDefinitionNode > = Object . create ( null ) ;
299
324
for ( const definition of document . definitions ) {
@@ -353,6 +378,7 @@ export function buildExecutionContext(
353
378
typeResolver : typeResolver ?? defaultTypeResolver ,
354
379
subscribeFieldResolver : subscribeFieldResolver ?? defaultFieldResolver ,
355
380
errors : [ ] ,
381
+ errorBehavior : onError ?? 'PROPAGATE' ,
356
382
} ;
357
383
}
358
384
@@ -591,6 +617,7 @@ export function buildResolveInfo(
591
617
rootValue : exeContext . rootValue ,
592
618
operation : exeContext . operation ,
593
619
variableValues : exeContext . variableValues ,
620
+ errorBehavior : exeContext . errorBehavior ,
594
621
} ;
595
622
}
596
623
@@ -599,10 +626,25 @@ function handleFieldError(
599
626
returnType : GraphQLOutputType ,
600
627
exeContext : ExecutionContext ,
601
628
) : null {
602
- // If the field type is non-nullable, then it is resolved without any
603
- // protection from errors, however it still properly locates the error.
604
- if ( isNonNullType ( returnType ) ) {
629
+ if ( exeContext . errorBehavior === 'PROPAGATE' ) {
630
+ // If the field type is non-nullable, then it is resolved without any
631
+ // protection from errors, however it still properly locates the error.
632
+ // Note: semantic non-null types are treated as nullable for the purposes
633
+ // of error handling.
634
+ if ( isNonNullType ( returnType ) ) {
635
+ throw error ;
636
+ }
637
+ } else if ( exeContext . errorBehavior === 'ABORT' ) {
638
+ // In this mode, any error aborts the request
605
639
throw error ;
640
+ } else if ( exeContext . errorBehavior === 'NO_PROPAGATE' ) {
641
+ // In this mode, the client takes responsibility for error handling, so we
642
+ // treat the field as if it were nullable.
643
+ } else {
644
+ invariant (
645
+ false ,
646
+ 'Unexpected errorBehavior setting: ' + inspect ( exeContext . errorBehavior ) ,
647
+ ) ;
606
648
}
607
649
608
650
// Otherwise, error protection is applied, logging the error and resolving
0 commit comments