payloadcms/payload · error · APIError

Could not retrieve sanitized join config for ${collection}.

Error message

Could not retrieve sanitized join config for ${collection}.

What it means

Thrown by `buildJoinAggregation` after it has confirmed the raw `collectionConfig.joins` is non-empty, but then fails to read the sanitized join config at `adapter.payload.collections[collection]?.config?.joins`. The sanitized (runtime) config is produced during init; its absence means the collection was not fully sanitized/registered under that slug.

Source

Thrown at packages/db-mongodb/src/utilities/buildJoinAggregation.ts:61

  locale,
  projection,
  versions,
}: BuildJoinAggregationArgs): Promise<PipelineStage[]> => {
  if (!adapter.useJoinAggregations) {
    return []
  }
  if (
    (Object.keys(collectionConfig.joins).length === 0 &&
      collectionConfig.polymorphicJoins.length == 0) ||
    joins === false
  ) {
    return []
  }

  const joinConfig = adapter.payload.collections[collection]?.config?.joins

  if (!joinConfig) {
    throw new APIError(`Could not retrieve sanitized join config for ${collection}.`)
  }

  const aggregate: PipelineStage[] = []
  const polymorphicJoinsConfig = adapter.payload.collections[collection]?.config?.polymorphicJoins

  if (!polymorphicJoinsConfig) {
    throw new APIError(`Could not retrieve sanitized polymorphic joins config for ${collection}.`)
  }

  for (const join of polymorphicJoinsConfig) {
    if (projection && !projection[join.joinPath]) {
      continue
    }

    if (joins?.[join.joinPath] === false) {
      continue
    }

View on GitHub (pinned to 00c58b35c0)

Solutions

  1. Verify the `collection` slug exactly matches a key in `adapter.payload.collections`.
  2. Ensure join definitions are valid so they survive sanitization.
  3. Await `payload.init()` before querying.
  4. Check for duplicate slug registrations that overwrite the sanitized entry.

Example fix

// before
await payload.find({ collection: 'posts', joins: { author: {} } }) // 'posts' not registered
// after
await payload.find({ collection: 'Posts', joins: { author: {} } })
Defensive patterns

Strategy: validation

Validate before calling

function assertJoinConfig(payload, collection) {
  const cfg = payload.collections[collection]?.config?.joins
  if (!cfg) throw new Error(`No sanitized join config for ${collection}`)
  return cfg
}

Type guard

const hasSanitizedJoins = (payload, c) =>
  Boolean(payload.collections[c]?.config?.joins)

Try / catch

try { await payload.find({ collection, joins: {...} }) }
catch (e) { if (/sanitized join config/.test(e.message)) handleBadJoinTarget(collection) else throw e }

Prevention

When it happens

Trigger: A query requesting joins on a collection whose sanitized runtime config is missing the `joins` field — slug mismatch between the request and `adapter.payload.collections`, joins stripped during sanitization, or a query issued mid-init before sanitization completed.

Common situations: Collection renamed so the request slug no longer matches the registered key; a join definition failed validation and was dropped during sanitization; querying during init; duplicate slug registration shadowing the real config; casing/whitespace mismatch in the slug.

Related errors


AI-assisted analysis of payloadcms/payload@00c58b35c0 (2026-08-12). Data as JSON: /api/errors/230ac7310b01ae31. Report an issue: GitHub.