Report QueryComplexity variable coercion errors instead of throwing - #1969
Open
ruudk wants to merge 1 commit into
Open
Report QueryComplexity variable coercion errors instead of throwing#1969ruudk wants to merge 1 commit into
ruudk wants to merge 1 commit into
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
This PR updates the QueryComplexity validation rule so variable coercion failures are reported as regular validation errors (via the validation context) instead of throwing, bringing it in line with how DocumentValidator::validate() is documented to behave.
Changes:
- Report variable coercion errors through
$context->reportError()and abandon complexity analysis for that document. - Reuse the per-document coerced variable cache when building field arguments (avoids re-coercing per field with a
complexityFn). - Add regression tests covering coercion failures (including multiple errors, error locations, and per-document reset), plus a changelog entry.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
src/Validator/Rules/QueryComplexity.php |
Converts coercion failures from thrown exceptions into reported validation errors and stops complexity enforcement when coercion fails. |
tests/Validator/QueryComplexityTest.php |
Adds coverage for coercion-failure behavior (messages, locations, multiple errors, caching/reset semantics). |
CHANGELOG.md |
Documents the fix under Unreleased. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
`DocumentValidator::validate()` is documented to return validation errors, and every other rule reports them through the validation context. But `QueryComplexity` coerces variable values (it needs them to evaluate @include/@Skip and to build arguments for `complexityFn`) and threw a raw `Error` when coercion failed. Callers using `DocumentValidator` directly rather than `GraphQL::promiseToExecute()` — which sets the variables and wraps everything in try/catch — got an uncaught exception for something that is a plain input problem. Coercion errors now go to `$context->reportError()` and complexity analysis is abandoned for the rest of the document: without usable variable values the computed complexity is meaningless, so reporting a max-complexity error on top of it would be misleading, and calling a user-supplied `complexityFn` with empty arguments could throw. For the same reason `getQueryComplexity()` is reset to 0, so it cannot hand back the partial sum accumulated before coercion failed. This also improves the errors themselves. The old code concatenated the messages of all coercion errors into one `Error`, discarding the source locations; each error is now reported individually with the location of its variable definition, matching what the executor produces for the same bad input. While here, `buildFieldArguments()` reuses the per-document coercion cache instead of coercing all variables again for every field that has a `complexityFn`. Fixes #1967
ruudk
force-pushed
the
fix/1967-query-complexity-reports-coercion-errors
branch
from
August 25, 2026 12:37
986d73b to
1d2e49c
Compare
ruudk
marked this pull request as ready for review
August 25, 2026 12:42
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.
DocumentValidator::validate()is documented to return validation errors, and every other rule reports them through the validation context. ButQueryComplexitycoerces variable values (it needs them to evaluate @include/@Skip and to build arguments forcomplexityFn) and threw a rawErrorwhen coercion failed. Callers usingDocumentValidatordirectly rather thanGraphQL::promiseToExecute()— which sets the variables and wraps everything in try/catch — got an uncaught exception for something that is a plain input problem.Coercion errors now go to
$context->reportError()and complexity analysis is abandoned for the rest of the document: without usable variable values the computed complexity is meaningless, so reporting a max-complexity error on top of it would be misleading, and calling a user-suppliedcomplexityFnwith empty arguments could throw. For the same reasongetQueryComplexity()is reset to 0, so it cannot hand back the partial sum accumulated before coercion failed.This also improves the errors themselves. The old code concatenated the messages of all coercion errors into one
Error, discarding the source locations; each error is now reported individually with the location of its variable definition, matching what the executor produces for the same bad input.While here,
buildFieldArguments()reuses the per-document coercion cache instead of coercing all variables again for every field that has acomplexityFn.Fixes #1967