{"record":{"id":"138bf09568f9deeb","repo":"payloadcms/payload","slug":"orderable-joins-must-target-a-single-collection","errorCode":null,"errorMessage":"Orderable joins must target a single collection","messagePattern":"Orderable joins must target a single collection","errorType":"exception","errorClass":"APIError","httpStatus":500,"severity":"error","filePath":"packages/payload/src/fields/config/sanitizeJoinField.ts","lineNumber":63,"sourceCode":"    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')\n  }\n\n  if (Array.isArray(field.collection)) {\n    for (const collection of field.collection) {\n      const sanitizedField = {\n        ...field,\n        collection,\n      } as FlattenedJoinField\n\n      sanitizeJoinField({\n        config,\n        field: sanitizedField,\n        joinPath,\n        joins,\n        parentIsLocalized,\n        polymorphicJoins,\n        validateOnly: true,\n      })","sourceCodeStart":45,"sourceCodeEnd":81,"githubUrl":"https://github.com/payloadcms/payload/blob/00c58b35c0ed348ddc22daabf467b139727214fd/packages/payload/src/fields/config/sanitizeJoinField.ts#L45-L81","documentation":"An `orderable: true` join field targets more than one collection (`collection` is an array — a polymorphic join). Ordering rows across collections requires a single target table with a shared order column, so polymorphic orderable joins are rejected.","triggerScenarios":"`{ type: 'join', name: 'x', orderable: true, collection: ['posts', 'pages'], on: 'owner' }`.","commonSituations":"Wanting a polymorphic join that is also manually reorderable; copy-pasting an orderable join and adding a second collection.","solutions":["Narrow the join to a single target collection (`collection: 'posts'`) if you need ordering.","If polymorphism is required, set `orderable: false` (or omit it) and accept default ordering.","Split into two separate orderable joins, one per collection."],"exampleFix":"// before\n{ type: 'join', name: 'items', orderable: true, collection: ['posts', 'pages'], on: 'owner' }\n// after\n{ type: 'join', name: 'posts', orderable: true, collection: 'posts', on: 'owner' }","handlingStrategy":"validation","validationCode":"function findOrderablePolymorphicJoins(fields) {\n  const bad = []\n  function walk(list) {\n    for (const f of list) {\n      if (f?.type === 'join' && f.orderable && Array.isArray(f.collection)) bad.push(f.name)\n      if (Array.isArray(f?.fields)) walk(f.fields)\n    }\n  }\n  walk(fields)\n  return bad\n}","typeGuard":"function orderableJoinTargetsSingleCollection(f: any): boolean {\n  return f?.type !== 'join' || !f.orderable || !Array.isArray(f.collection)\n}","tryCatchPattern":"try {\n  await payload.init({ config })\n} catch (err) {\n  if (err?.name === 'APIError' && /Orderable joins must target a single/i.test(err?.message ?? '')) {\n    console.error('orderable join with multiple collections')\n  }\n  throw err\n}","preventionTips":["Keep orderable joins single-collection; use multiple joins for polymorphism.","Lint join fields: `orderable` + array `collection` is always invalid."],"tags":["join","orderable","polymorphic","config","schema"],"backgroundTag":null,"analyzedSha":"00c58b35c0ed348ddc22daabf467b139727214fd","analyzedAt":"2026-08-12T20:45:03.758Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}