Skip to content

Throw RequestError for scalar batch entries - #1993

Merged
spawnia merged 4 commits into
masterfrom
reject-non-array-batch-entries
Oct 12, 2026
Merged

spawnia merged 4 commits into
masterfrom
reject-non-array-batch-entries

Conversation

@spawnia

@spawnia spawnia commented Oct 12, 2026 •

Copy link
Copy Markdown
Collaborator

Malformed batch bodies such as ["x"] caused an uncaught TypeError instead of a RequestError.
Helper::parseRequestParams() now rejects scalar batch entries.

An object with a non-null key `0` still counts as a batch, so the message names the offending key

{"query":"{ a }","0":"x"} fails with Expected batch entry query to be an object, got: "{ a }".
Batch detection stays isset($bodyParams[0]), so {"0":null,"query":"{ a }"} is still a single operation.
No other server checked has a dedicated message for this case: JS servers detect batches with Array.isArray, and laragraph/utils#27 also uses a generic message.

The fix targets master only, not 14.x

14.x has the same bug, but its last release was https://github.com/webonyx/graphql-php/releases/tag/v14.11.10 in 2023.

🤖 Generated with Claude Code

parseRequestParams() passed every batch entry to OperationParams::create(),
so bodies like ["x"] or {"query":"{ a }","0":"x"} threw a TypeError.

🤖 Generated with Claude Code
@spawnia
spawnia requested a balanced review from Copilot October 12, 2026 14:00
@spawnia
spawnia marked this pull request as ready for review October 12, 2026 14:00

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Nested-array and null batch entries still bypass the new validation.

1 open finding
What changed in this PR

Improves malformed GraphQL batch-request handling by converting scalar-entry failures into RequestError.

Changes:

  • Validates batch entries before creating operation parameters.
  • Adds regression tests and changelog documentation.
File Description
src/​Server/​Helper.php Adds batch-entry validation.
tests/​Server/​RequestParsingTest.php Tests malformed batches and key-zero handling.
CHANGELOG.md Documents the fix.

🧠 Review effort: Balanced


💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/Server/Helper.php Resolved
🤖 Generated with Claude Code
For {"query":"{ a }","0":"x"} the message pointed at the valid query
without saying which key it came from.

🤖 Generated with Claude Code
Array entries such as ["x"] still pass, since associative decoding
makes them indistinguishable from objects.

🤖 Generated with Claude Code
@spawnia spawnia changed the title Throw RequestError for non-object batch entries Throw RequestError for scalar batch entries Oct 12, 2026

@github-actions github-actions Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Performance Alert ⚠️

Possible performance regression was detected for benchmark.
Benchmark result of this commit is worse than the previous benchmark result exceeding threshold 1.50.

Benchmark suite Current: c45b4bc Previous: 6a7c89a Ratio
BuildSchemaBench::benchBuildSchema 25.129 ms 14.001 ms 1.79
OverlappingFieldsCanBeMergedBench::benchRepeatedFields100 3.272 ms 1.743 ms 1.88
OverlappingFieldsCanBeMergedBench::benchRepeatedFields500 15.522 ms 8.614 ms 1.80
OverlappingFieldsCanBeMergedBench::benchRepeatedFields1000 31.437 ms 16.946 ms 1.86
OverlappingFieldsCanBeMergedBench::benchRepeatedFields2000 63.94 ms 35.356 ms 1.81
OverlappingFieldsCanBeMergedBench::benchRepeatedFields3000 95.805 ms 52.179 ms 1.84
VisitorBench::benchVisitIntrospectionWithEnterLeave 0.304 ms 0.159 ms 1.91
VisitorBench::benchVisitIntrospectionWithKindMap 0.3 ms 0.154 ms 1.95
VisitorBench::benchVisitIntrospectionWithKindCallable 0.277 ms 0.143 ms 1.94
VisitorBench::benchVisitIntrospectionWithEnterLeaveMap 0.304 ms 0.16 ms 1.90
VisitorBench::benchVisitNestedWithEnterLeave 0.07 ms 0.036 ms 1.94
ScalarOverrideBench::benchExecuteWithoutOverride 0.162 ms 0.081 ms 2
ScalarOverrideBench::benchExecuteWithTypesOverride 0.164 ms 0.081 ms 2.02
StarWarsBench::benchSchema 0.005 ms 0.003 ms 1.67
StarWarsBench::benchHeroQuery 0.328 ms 0.178 ms 1.84
StarWarsBench::benchNestedQuery 0.719 ms 0.396 ms 1.82
StarWarsBench::benchQueryWithFragment 0.766 ms 0.425 ms 1.80
StarWarsBench::benchQueryWithInterfaceFragment 0.718 ms 0.391 ms 1.84
StarWarsBench::benchStarWarsIntrospectionQuery 7.223 ms 3.954 ms 1.83
HugeSchemaBench::benchSchema 12.919 ms 7.536 ms 1.71
HugeSchemaBench::benchSmallQuery 15.148 ms 8.289 ms 1.83
HugeSchemaBench::benchSmallQueryLazy 16.741 ms 9.704 ms 1.73
LexerBench::benchIntrospectionQuery 0.299 ms 0.162 ms 1.85
LexerBench::benchDeeplyIndentedQuery 1.933 ms 1.054 ms 1.83
DeferredBench::benchSingleDeferred 0.001 ms 0 ms +∞
DeferredBench::benchNestedDeferred 0.003 ms 0.001 ms 3
DeferredBench::benchChain5 0.005 ms 0.003 ms 1.67
DeferredBench::benchChain100 0.082 ms 0.044 ms 1.86
DeferredBench::benchManyDeferreds 0.45 ms 0.225 ms 2
DeferredBench::benchManyNestedDeferreds 14.384 ms 6.324 ms 2.27
DeferredBench::bench1000Chains 3.56 ms 1.766 ms 2.02

This comment was automatically generated by workflow using github-action-benchmark.

@spawnia
spawnia merged commit 4c966a2 into master Oct 12, 2026
22 checks passed
@spawnia
spawnia deleted the reject-non-array-batch-entries branch October 12, 2026 14:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants