payloadcms / payloadcms/payload

GraphQL queries fail on Cloudflare Workers with "Unexpected input type" — caused by createComplexityRule (graphql-query-complexity)

Open
#17,771 3 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
TypeScript
Stars
44.8k
Forks
4.2k
Avg merge
2d 21h
Merged PRs (30d)
53

Description

Describe the Bug

Every GraphQL query/mutation fails on Cloudflare Workers with Unexpected input type: Int (and Unexpected input type: mutationUserInput! for mutations). The same setup works fine on Node.

Reproduced with the official with-cloudflare-d1 template (Payload 3.82.1) running on vinext (Cloudflare Workers target, wrangler dev local workerd). The template README notes GraphQL "is not currently guaranteed" on Workers (previously linked to workerd#5175, which is closed and unrelated) — but this issue has a precise root cause worth fixing.

Repro

Standard GraphQL query against the template:

curl -X POST http://localhost:8787/api/graphql \
  -H 'content-type: application/json' \
  -d '{"query":"{ Users(limit: 1) { docs { id email } } }"}'

Response (Workers/workerd):

[{"message":"Unexpected input type: Int"}]

Mutation fails the same way: Unexpected input type: mutationUserInput!.

Root cause (bisected)

The error comes from graphql's astFromValue/coerceInputValue invariant. Bisection on the @payloadcms/next GraphQL route handler (routes/graphql/handler.js):

  • configToSchema output is correct (Query.Users args = limit: Int, where: User_where, …)
  • Executing the query directly via graphql.execute works (reaches access control)
  • graphql-http's createHandler works without extra validation rules
  • Adding validationRules (payload's createComplexityRule from the vendored graphql-query-complexity) makes it fail — this is the exact combination the real endpoint uses
  • Node validation: validate(schema, query, specifiedRules.concat([complexityRule]))no errors (works fine)
  • Same code in workerd → Unexpected input type: Int

So createComplexityRule (from @payloadcms/graphql's vendored graphql-query-complexity) misbehaves under workerd.

Expected behavior

GraphQL queries (including limit/where args) validate and execute on Cloudflare Workers, same as Node.

Environment
  • Payload 3.82.1, @payloadcms/next 3.82.1, @payloadcms/graphql 3.82.1
  • wrangler 4.116.0 / workerd (local dev), vinext 1.0.0-beta.2, Vite 8.2.1
Impact

GraphQL API is entirely unusable on Workers (both queries and mutations). REST works fine. Full reproduction project with 21-check API coverage script is available on request.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in the @payloadcms/next GraphQL route handler at routes/graphql/handler.js and trace how the vendored graphql-query-complexity createComplexityRule is passed as a validation rule. Reproduce the failure with the provided curl request under workerd, then compare validation with and without the complexity rule. Done means queries and mutations validate and execute on Cloudflare Workers without the Unexpected input type errors while Node behavior remains unchanged.

Written by the indexing model from the issue text.

Assessment

Tech stack
graphql, typescript
Domain
api, backend, cloud
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.