payloadcms / payloadcms/payload

GraphQL schema creation fails with duplicate type name for recursive depth-limited block structures

Open
#17,302 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

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

Description

Describe the Bug

Using the documented community pattern for recursive block structures — a depth-limited factory that returns one block config object per nesting level, all sharing the same slug and interfaceName (see e.g. discussion #4238) — breaks GraphQL schema creation entirely:

Error: Schema must contain uniquely named types but contains multiple types named "RecursiveItemBlock".

Every request against /api/graphql then returns a 500, including a trivial { __typename } query. TypeScript type generation handles the same pattern fine (deduplicates into interfaces), and the REST/Local APIs work normally — only the GraphQL schema build fails.

Root cause: the blocks handler in packages/graphql/src/schema/fieldToSchemaMap.ts deduplicates block types via the graphqlResult.types.blockTypes registry (keyed by block slug), but it only registers the newly built type after calling objectType.getFields(). That call eagerly resolves the type's fields, which walks nested blocks fields and re-enters the handler while the registry entry is still missing — so each nesting level constructs its own GraphQLObjectType with the same name, and new GraphQLSchema(...) rejects the schema.

Affects both v3 (reproduced on 3.85.1 and 3.86.0) and current main.

Fix PR (register the type before forcing field resolution, plus regression tests): #17300

Link to the code that reproduces this issue

https://github.com/alphanull/payload/tree/repro/graphql-recursive-blocks

(follows the reproduction guide: single commit adding a recursive block field to test/_community's Posts collection)

Reproduction Steps
  1. Check out the reproduction branch and run pnpm install.
  2. Run pnpm dev:generate-graphql-schema _community (or start pnpm dev _community and POST {"query":"{ __typename }"} to /api/graphql).
  3. Schema creation throws Schema must contain uniquely named types but contains multiple types named "RecursiveItemBlock".

The added config is just:

const buildRecursiveBlock = (depth: number): Block => {
  const fields: Field[] = [{ name: 'label', type: 'text', required: true }]

  if (depth > 1) {
    fields.push({
      name: 'children',
      type: 'blocks',
      blocks: [buildRecursiveBlock(depth - 1)],
    })
  }

  return {
    slug: 'recursiveItem',
    fields,
    interfaceName: 'RecursiveItemBlock',
  }
}

// in a collection:
{
  name: 'recursiveBlockField',
  type: 'blocks',
  blocks: [buildRecursiveBlock(3)],
}
Which area(s) are affected?

area: graphql

Environment Info
Binaries:
  Node: 24.18.0
  npm: 11.16.0
  Yarn: N/A
  pnpm: 11.5.2
Relevant Packages:
  payload: 3.86.0
Operating System:
  Platform: linux
  Arch: arm64
  Version: #1 SMP Thu Jun 25 13:45:40 UTC 2026
  Available memory (MB): 7937
  Available CPU cores: 4

Also reproduced against current main (4.0.0-beta.0) with Node 24.18.0.

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 packages/graphql/src/schema/fieldToSchemaMap.ts and reproduce the failure with pnpm dev:generate-graphql-schema _community or the provided reproduction branch. Review the existing regression tests from PR #17300; done means recursive block configurations build a valid GraphQL schema without duplicate RecursiveItemBlock types.

Written by the indexing model from the issue text.

Assessment

Tech stack
graphql, typescript
Domain
api, backend
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
30/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.