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
- Check out the reproduction branch and run
pnpm install.
- Run
pnpm dev:generate-graphql-schema _community (or start pnpm dev _community and POST {"query":"{ __typename }"} to /api/graphql).
- 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.
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
slugandinterfaceName(see e.g. discussion #4238) — breaks GraphQL schema creation entirely:Every request against
/api/graphqlthen 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
blockshandler inpackages/graphql/src/schema/fieldToSchemaMap.tsdeduplicates block types via thegraphqlResult.types.blockTypesregistry (keyed by block slug), but it only registers the newly built type after callingobjectType.getFields(). That call eagerly resolves the type's fields, which walks nestedblocksfields and re-enters the handler while the registry entry is still missing — so each nesting level constructs its ownGraphQLObjectTypewith the same name, andnew 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
pnpm install.pnpm dev:generate-graphql-schema _community(or startpnpm dev _communityand POST{"query":"{ __typename }"}to/api/graphql).Schema must contain uniquely named types but contains multiple types named "RecursiveItemBlock".The added config is just:
Which area(s) are affected?
area: graphql
Environment Info
Also reproduced against current
main(4.0.0-beta.0) with Node 24.18.0.