payloadcms/payload · error · APIError

Join Model was not found for ${collectionConfig.slug}

Error message

Join Model was not found for ${collectionConfig.slug}

What it means

Thrown when the join target collection's Mongoose model can't be resolved — neither `adapter.versions[collectionConfig.slug]` (drafts path) nor `adapter.collections[collectionConfig.slug]` exist. The collection config exists but its DB model was not built/registered by the adapter.

Source

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

      if (!collectionConfig) {
        throw new APIError(
          `Collection config for ${join.field.collection.toString()} was not found`,
        )
      }

      let JoinModel: CollectionModel | undefined

      const useDrafts = (draftsEnabled || versions) && hasDraftsEnabled(collectionConfig)

      if (useDrafts) {
        JoinModel = adapter.versions[collectionConfig.slug]
      } else {
        JoinModel = adapter.collections[collectionConfig.slug]
      }

      if (!JoinModel) {
        throw new APIError(`Join Model was not found for ${collectionConfig.slug}`)
      }

      const {
        count,
        limit: limitJoin = join.field.defaultLimit ?? 10,
        page,
        sort: sortJoin = join.field.defaultSort || collectionConfig.defaultSort,
        where: whereJoin = {},
      } = joins?.[join.joinPath] || {}

      if (Array.isArray(join.field.collection)) {
        throw new Error('Unreachable')
      }

      const fields = useDrafts
        ? buildVersionCollectionFields(adapter.payload.config, collectionConfig, true)
        : collectionConfig.flattenedFields

View on GitHub (pinned to 00c58b35c0)

Solutions

  1. Await `payload.init()` fully before issuing join queries.
  2. Inspect startup logs for model-build errors on the named collection.
  3. Verify `versions`/`draftsAndPublish` config is consistent and valid.
  4. Restart the process to rebuild all models from scratch.

Example fix

// startup swallowed an error
await payload.init() // throws clearly if a model fails to build
// then issue join queries
Defensive patterns

Strategy: validation

Validate before calling

function assertJoinModel(adapter, slug) {
  const m = adapter.collections[slug] || adapter.versions[slug]
  if (!m) throw new Error(`No Mongoose model built for ${slug}`)
  return m
}

Type guard

const hasJoinModel = (adapter, slug) =>
  Boolean(adapter.collections[slug] || adapter.versions[slug])

Try / catch

try { await payload.find({ collection, joins }) }
catch (e) { if (/Join Model was not found/.test(e.message)) await restartOrWaitInit() else throw e }

Prevention

When it happens

Trigger: The join target collection is registered in config but its Mongoose model was never constructed during adapter init (model build failed or was skipped), or a query runs before models are built.

Common situations: Init ordering/race; an earlier model-build error for that collection was swallowed; drafts/versions flag inconsistency between config and the models actually built; partial init after a thrown error.

Related errors


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