Currently GraphQL v17 is in alpha, this guide is based on the alpha release and is subject to change.
Breaking changes
Default values
GraphQL schemas allow default values for input fields and arguments. Historically, GraphQL.js did not rigorously validate or coerce these defaults during schema construction, leading to potential runtime errors or inconsistencies. For example:
- A default value of “5” (string) for an Int-type argument would pass schema validation but fail at runtime.
- Internal serialization methods like astFromValue could produce invalid ASTs if inputs were not properly coerced.
With the new changes default values will be validated and coerced during schema construction.
input ExampleInput {
value: Int = "invalid" # Now triggers a validation error
}This goes hand-in-hand with the deprecation of astFromValue in favor of valueToLiteral or default: { value: <externalValue> }.
// Before (deprecated)
const defaultValue = astFromValue(internalValue, type);
// After
const defaultValue = valueToLiteral(externalValue, type);If you want to continue using the old behavior, you can use defaultValue in your schema definitions. The new
behavior will be exposed as default: { literal: <literal> }.
GraphQLError constructor arguments
The GraphQLError constructor now only accepts a message and options object as arguments. Previously, it also accepted positional arguments.
- new GraphQLError('message', 'source', 'positions', 'path', 'originalError', 'extensions');
+ new GraphQLError('message', { source, positions, path, originalError, extensions });createSourceEventStream arguments
The createSourceEventStream function now only accepts an object as an argument. Previously, it also accepted positional arguments.
- createSourceEventStream(schema, document, rootValue, contextValue, variableValues, operationName);
+ createSourceEventStream({ schema, document, rootValue, contextValue, variableValues, operationName });execute will error for incremental delivery
The execute function will now throw an error if it sees a @defer or @stream directive. Use experimentalExecuteIncrementally instead.
If you know you are dealing with incremental delivery requests, you can replace the import.
- import { execute } from 'graphql';
+ import { experimentalExecuteIncrementally as execute } from 'graphql';Remove incremental delivery support from subscribe
In case you have fragments that you use with defer/stream that end up in a subscription,
use the if argument of the directive to disable it in your subscription operation
subscribe return type
The subscribe function can now also return a non-Promise value, previously this was only a Promise.
This shouldn’t change a lot as await value will still work as expected. This could lead to
some typing inconsistencies though.
Remove singleResult from incremental results
You can remove branches that check for singleResult in your code, as it is no longer used.
Node support
Dropped support for Node 14 (subject to change)
Removed TokenKindEnum, KindEnum and DirectiveLocationEnum types
We have removed the TokenKindEnum, KindEnum and DirectiveLocationEnum types,
use Kind, TokenKind and DirectiveLocation instead. https://github.com/graphql/graphql-js/pull/3579
Removed graphql/subscription module
use graphql/execution instead for subscriptions, all execution related exports have been
unified there.
Removed GraphQLInterfaceTypeNormalizedConfig export
Use ReturnType<GraphQLInterfaceType['toConfig']> if you really need this
Empty AST collections will be undefined
Empty AST collections will be presented by undefined rather than an empty array.
Info.variableValues
The shape of Info.variableValues has changed to be an object containing
sources and coerced as keys.
A Source contains the signature and provided value pre-coercion for the
variable. A signature is an object containing the name, input-type and
defaultValue for the variable.
Stream directive can’t be on multiple instances of the same field
The @stream directive can’t be on multiple instances of the same field,
this won’t pass validate anymore.
See https://github.com/graphql/graphql-js/pull/4342
Stream initialCount becomes non-nullable
The initialCount argument of the @stream directive is now non-nullable.
See https://github.com/graphql/graphql-js/pull/4322
GraphQLSchemas converted to configuration may no longer be assumed valid
The assumeValid config property exported by the GraphQLSchema.toConfig() method now passes through the original
flag passed on creation of the GraphQLSchema.
Previously, the assumeValid property would be to true if validation had been run, potentially concealing the original intent.
See https://github.com/graphql/graphql-js/pull/4244 and https://github.com/graphql/graphql-js/issues/3448
coerceInputValue returns undefined on error
coerceInputValue now aborts early when an error occurs, to optimize execution speed on the happy path.
Use the validateInputValue helper to retrieve the actual errors.
Removals
- Removed deprecated
getOperationTypefunction, usegetRootTypeon theGraphQLSchemainstance instead - Removed deprecated
getVisitFnfunction, usegetEnterLeaveForKindinstead - Removed deprecated
printErrorandformatErrorutilities, you can usetoStringortoJSONon the error as a replacement - Removed deprecated
assertValidNameandisValidNameErrorutilities, useassertNameinstead - Removed deprecated
assertValidExecutionArgumentsfunction, useassertValidSchemainstead - Removed deprecated
getFieldDefFnfromTypeInfo - Removed deprecated
TypeInfofromvalidatehttps://github.com/graphql/graphql-js/pull/4187
Deprecations
- Deprecated
astFromValueusevalueToLiteralinstead, when leveragingvalueToLiteralensure that you are working with externally provided values i.e. the SDL provided defaultValue to a variable. - Deprecated
valueFromASTusecoerceInputLiteralinstead - Deprecated
findBreakingChanges()andfindDangerousChanges(). UsefindSchemaChanges()instead, which can also be used to find safe changes. - Deprecated
serialize.parseValue, andparseLiteralproperties on scalar type configuration. UsecoerceOutputValue,coerceInputValue, andcoerceInputLiteralinstead.
Experimental Features
Experimental Support for Incremental Delivery
- Spec PR / RFC
- enabled only when using
experimentalExecuteIncrementally(), use of a schema or operation with@defer/@streamdirectives withinexecute()will now throw. - enable early execution with the new
enableEarlyExecutionconfiguration option forexperimentalExecuteIncrementally().
Experimental Support for Fragment Arguments
- Spec PR
- enable with the new
experimentalFragmentArgumentsconfiguration option forparse(). - new experimental
Kind.FRAGMENT_ARGUMENTfor visiting - new experimental
TypeInfomethods and options for handling fragment arguments. - coerce AST via new function
coerceInputLiteral()with experimental fragment variables argument (as opposed to deprecatedvalueFromAST()function).
Features
- Added
hideSuggestionsoption toexecute/validate/subscribe/… to hide schema-suggestions in error messages - Added
abortSignaloption tographql(),execute(), andsubscribe()allows cancellation of these methods; theabortSignalcan also be passed to field resolvers to cancel asynchronous work that they initiate. extensionssupportsymbolkeys, in addition to the normal string keys.- Added ability for resolver functions to return async iterables.
- Added
perEventExecutorexecution option to allows specifying a custom executor for subscription source stream events, which can be useful for preparing a per event execution context argument. - Added
validateInputValueandvalidateInputLiteralhelpers to validate input values and literals, respectively. - Added
replaceVariableValueshelper to replace variables within complex scalars uses as inputs. Internally, this allows variables embedded within complex scalars to finally use the correct default values. - Added new
printDirectivehelper.