At a glance
- Identifier: #1065
- Stage: RFC0: Strawman
- Champion: @benjie
- PR: SemanticNonNull type (null only on error)
- Commit pushed: Add IsValidImplementationFieldType updates on 2024-01-03 by @benjie
- Spec PR created on 2023-11-24 by benjie
- Commit pushed: Change name to 'SemanticNonNull' and syntax to bang prefix on 2023-11-24 by @benjie
- 3 commits pushed on 2023-10-04:
TL;DR: Introduces a new type wrapper, Semantic-Non-Null, which represents that a value will not be null unless an error happens, and if an error does happen then this
nulldoes not bubble.
GraphQL schema designers must use non-nullable types sparingly because if a non-nullable type were to raise an error then the entire selection set it is within will be destroyed, leading to clients receiving less usable data and making writing the results to a normalized cache a dangerous action. Because of this, nullable-by-default is a best practice in GraphQL, and non-null type wrappers should only be used for fields that the schema designer is confident will never raise an error - not just in the current schema, but in all future schemas.
Many GraphQL consumers choose to ignore the entire response from the server when any error happens, one reason for this is because the null bubbling behavior makes writing to normalized caches dangerous. For these users, when an error doesn't happen, the nullable fields they are dealing with can be frustrating because their type generation requires them to handle the null case even if it may never happen in practice, which can lead to a lot of unnecessary code that will never execute. There is currently no way for the type generators to know that a field will never be null unless there's an associated error.
We can categorise that there are effectively two types of
null: where a position is
nulland there's a related error (with matching or prefixed path) in the
errorslist - indicates that something went wrong.
null: where a position is
nulland there is no related error - this data truly is null (e.g. a user having not yet set their avatar may have
avatar: null; this is not an error).
This PR introduces a new wrapper type in addition to List and Non-Null, called Semantic-Non-Null. The Semantic-Non-Null type indicates that the field will never be a semantic
null- it will not be
nullin the normal course of business, but can be null only if accompanied by an error in the
errorslist (i.e. an "error
null"). Thus a client that throws out all responses with errors will never see a
nullin this position. Also, critically, any
nullraised by this field will not bubble and thus if an error is found with the exact path to this
nullthen it is safe to store the result (including the error) into a normalized cache.
In SDL the Semantic-Non-Null wrapper is currently represented by a
!prefix (as opposed to the
!suffix for a strict Non-Null).
Thus we have the following:
# Type description Syntax Result values
string, or error
null, or semantic
string, or error
3above are exactly the same as in the current GraphQL specification, this PR introduces
2which sits in the middle.
All existing schemas are automatically supported because the meaning of
To ensure that all existing clients are automatically supported, this PR introduces the
__Field.typewhich defaults to
false. Clients that do not pass
includeSemanticNonNull: truewill see all Semantic-Non-Null types stripped, which will have the effect of making them appear as if they were the unadorned types. This is safe, since it means these clients will need to handle both error nulls and semantic nulls (as they traditionally would have) even though we know that a semantic null will never happen in practice.
All existing GraphQL documentation, tutorials, examples, and everything else we've built over the last 8 years remains valid since the meaning of
This PR is almost identical to #1048, but it changes the name of the new type wrapper from Null-Only-On-Error to Semantic-Non-Null, and changes the syntax from
!String. It addresses the True Nullability Schema discussion raised by @captbaritone and incorporates/adapts some of the terminology from @leebyron's Strict Semantic Nullability proposal.