{"record":{"id":"fbd543883fd01307","repo":"payloadcms/payload","slug":"join-fields-cannot-be-added-to-arrays-blocks-or-g","errorCode":null,"errorMessage":"Join fields cannot be added to arrays, blocks or globals.","messagePattern":"Join fields cannot be added to arrays, blocks or globals\\.","errorType":"exception","errorClass":"APIError","httpStatus":500,"severity":"error","filePath":"packages/payload/src/fields/config/sanitizeJoinField.ts","lineNumber":45,"sourceCode":"  joins,\n  orderableJoins,\n  parentIsLocalized,\n  polymorphicJoins,\n  validateOnly,\n}: {\n  config: Config\n  field: FlattenedJoinField | JoinField\n  joinPath?: string\n  joins?: SanitizedJoins\n  /** Tracker for orderable join fields - populated during sanitization */\n  orderableJoins?: OrderableJoinInfo[]\n  parentIsLocalized: boolean\n  polymorphicJoins?: SanitizedJoin[]\n  validateOnly?: boolean\n}) => {\n  // the `joins` arg is not passed for globals or when recursing on fields that do not allow a join field\n  if (typeof joins === 'undefined') {\n    throw new APIError('Join fields cannot be added to arrays, blocks or globals.')\n  }\n  if (!field.admin) {\n    field.admin = {}\n  }\n  if (typeof field.maxDepth === 'undefined') {\n    field.maxDepth = 1\n  }\n  const join: SanitizedJoin = {\n    field,\n    joinPath: `${joinPath ? joinPath + '.' : ''}${field.name}`,\n    parentIsLocalized,\n    // @ts-expect-error - vestiges of when tsconfig was not strict. Feel free to improve\n    targetField: undefined,\n  }\n\n  // Orderable joins must target a single collection\n  if (field.orderable && Array.isArray(field.collection)) {\n    throw new APIError('Orderable joins must target a single collection')","sourceCodeStart":27,"sourceCodeEnd":63,"githubUrl":"https://github.com/payloadcms/payload/blob/00c58b35c0ed348ddc22daabf467b139727214fd/packages/payload/src/fields/config/sanitizeJoinField.ts#L27-L63","documentation":"A `join` field was placed where joins are not allowed: inside an array, inside a block, or on a global. The sanitizer detects this because the `joins` argument is `undefined` (it is only passed for top-level collection fields). Join fields need a single owning collection with a DB table, which arrays/blocks/globals cannot provide.","triggerScenarios":"A `join` field listed in the `fields` of an `array`, in a block's `fields`, or in a global's `fields`.","commonSituations":"Trying to model bi-directional relationships from inside a nested structure; assuming joins work like relationships everywhere; refactoring a top-level join into a group/array.","solutions":["Move the join field to the top level of a collection (not nested in array/block/group/tab-within-array).","If you need related data inside a nested structure, use a `relationship` field instead of a `join`.","For globals, model the reverse data as a relationship on a collection instead of a join on the global."],"exampleFix":"// before (join inside array)\n{ name: 'items', type: 'array', fields: [\n  { name: 'linked', type: 'join', collection: 'posts', on: 'owner' }\n]}\n// after (join on the collection top level)\nfields: [\n  { name: 'items', type: 'array', fields: [...] },\n  { name: 'linkedPosts', type: 'join', collection: 'posts', on: 'owner' }\n]","handlingStrategy":"validation","validationCode":"function findJoinsInDisallowedScopes(fields, inNested = false) {\n  const bad = []\n  for (const f of fields) {\n    if (f?.type === 'join' && inNested) bad.push(f.name)\n    if (Array.isArray(f?.fields)) bad.push(...findJoinsInDisallowedScopes(f.fields, true))\n    if (Array.isArray(f?.blocks)) for (const b of f.blocks) if (b?.fields) bad.push(...findJoinsInDisallowedScopes(b.fields, true))\n  }\n  return bad\n}\n// for globals, ALL joins are disallowed: scan global.fields with inNested=false but treat global context as disallowed","typeGuard":"function joinIsAtCollectionTopLevel(field, context): boolean {\n  return field?.type !== 'join' || (context === 'collection' && !context.nested)\n}","tryCatchPattern":"try {\n  await payload.init({ config })\n} catch (err) {\n  if (err?.name === 'APIError' && /Join fields cannot be added/i.test(err?.message ?? '')) {\n    console.error('join field placed in array/block/global')\n  }\n  throw err\n}","preventionTips":["Only declare `join` fields at the top level of a collection config.","Use `relationship` fields inside arrays/blocks/globals for nested references."],"tags":["join","array","block","global","config","schema","sanitization"],"backgroundTag":null,"analyzedSha":"00c58b35c0ed348ddc22daabf467b139727214fd","analyzedAt":"2026-08-12T20:45:03.758Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}