payloadcms/payload · error · APIError

Relationship was not found

Error message

Relationship was not found

What it means

`APIError('Relationship was not found')` from the hasMany branch of `getTableColumnFromPath`: when traversing a hasMany relationship through the relationships/join table, the adapter looks up the target field named by the relationship's `on` property in the target collection's `flattenedFields`. If that lookup fails (no field at that path on the target collection), the join condition cannot be built and the query aborts.

Source

Thrown at packages/drizzle/src/queries/getTableColumnFromPath.ts:392

        if (field.hasMany) {
          const relationTableName = `${adapter.tableNameMap.get(toSnakeCase(field.collection))}${adapter.relationshipsSuffix}`

          const existingTable = joins.find(
            (e) => e.queryPath === `${constraintPath}${field.name}._rels`,
          )

          const aliasRelationshipTable = (existingTable?.table ??
            getTableAlias({
              adapter,
              tableName: relationTableName,
            }).newAliasTable) as PgTableWithColumns<any>

          const relationshipField = getFieldByPath({
            fields: adapter.payload.collections[field.collection].config.flattenedFields,
            path: field.on,
          })
          if (!relationshipField) {
            throw new APIError('Relationship was not found')
          }

          if (!existingTable) {
            addJoinTable({
              condition: and(
                eq(
                  adapter.tables[rootTableName].id,
                  aliasRelationshipTable[
                    `${(relationshipField.field as RelationshipField).relationTo as string}ID`
                  ],
                ),
                like(aliasRelationshipTable.path, field.on),
              ),
              joins,
              queryPath: `${constraintPath}${field.name}._rels`,
              table: aliasRelationshipTable,
            })
          }

View on GitHub (pinned to 00c58b35c0)

Solutions

  1. Verify the relationship field's `on` value names an actual field on the target collection (check `flattenedFields`).
  2. If the target field was renamed, update the relationship's `on` to the new name and regenerate migrations.
  3. Ensure any plugin contributing the target field is loaded in the config running the query.

Example fix

// before: relationship 'on' references a field that no longer exists
//   { name: 'items', type: 'relationship', relationTo: 'items', hasMany: true, on: 'sectionID' }
//   but items collection renamed sectionID -> section_id
// after
//   { ..., on: 'section_id' }
Defensive patterns

Strategy: validation

Validate before calling

import { getFieldByPath } from 'payload'
const rel = payload.collections[collection].config.flattenedFields[seg]
if (rel?.hasMany) {
  const target = payload.collections[rel.relationTo].config
  if (!getFieldByPath({ fields: target.flattenedFields, path: rel.on })) {
    throw new Error(`Relationship '${seg}' on='${rel.on}' not found on '${rel.relationTo}'`)
  }
}

Type guard

const relationshipTargetFieldExists = (rel, payload) =>
  payload.collections[rel.relationTo]?.config.flattenedFields.some(f => f.name === rel.on)

Try / catch

try {
  await payload.find({ collection, where })
} catch (err) {
  if (err?.message === 'Relationship was not found') {
    payload.logger.error(`A hasMany relationship's 'on' field is missing on its target collection.`)
  }
  throw err
}

Prevention

When it happens

Trigger: Querying through a hasMany relationship whose `on` field refers to a field that doesn't exist on the related collection's config — e.g. after renaming/deleting the related field, or a stale `on` value, or a relationship whose target collection is misconfigured.

Common situations: Renaming the relationship target field without updating the relationship's `on`; relationship config pointing at a field added by a plugin that isn't loaded; copy-paste relationship config between collections with different field names.

Related errors


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