OneOf inhabitability fixes - #4458
Open
jbellenger wants to merge 4 commits into
Open
Conversation
…inhabitability-2 # Conflicts: # src/main/java/graphql/schema/validation/NoUnbrokenInputCycles.java # src/main/java/graphql/schema/validation/SchemaValidator.java # src/test/groovy/graphql/schema/validation/NoUnbrokenInputCyclesTest.groovy # src/test/groovy/graphql/schema/validation/SchemaValidatorTest.groovy
Contributor
Test ReportTest Results
Code Coverage (Java 25)
Changed Class Coverage (2 classes)
|
Merged
martinbonnin
approved these changes
Aug 24, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
OneOf input objects can be defined in a way that makes it impossible to create a value for that type. This breaks the spec's unwritten requirement that all input types be inhabited.
The simplest example of an uninhabited OneOf is the self-recursing
input Foo @oneOf { foo:Foo }. Trying to create a value for this type requires an infinitely nested object value, and should be invalid for the same reason that the spec currently considers the non-OneOf variantinput Foo { foo:Foo! }to be invalid.I have an open spec PR that updates the recursive input object requirements to consider OneOf input objects. The proposed algorithm was implemented in graphql-js here.
I previously added a version of these rules to graphql-java, but this was before I had a complete grasp on the problem and the validation is incomplete.
For example, this mixed-OneOf type graph also requires infinite values and is incorrectly allowed by graphql-java:
This PR closes this validation hole by porting over graphql-js's implementation of this validator.
Perf
The validator runs once per schema. It uses a worklist algorithm and takes time that is linear relative to the total number of input object fields in a schema. I've included a benchmark that tests a variety of different schemas:
The takeaway is that performance is relatively stable even for pathological input object graphs.