payloadcms/payload · error · APIError
Relationship field was not found
Error message
Relationship field was not found
What it means
For a join-type field in a nested query, buildSearchParam resolves the join's target relationship field via getFieldByPath on the collection's flattenedFields using field.on. If no field exists at that path, it throws APIError. The join field's `on` must point to an existing relationship field on the same collection.
Source
Thrown at packages/db-mongodb/src/queries/buildSearchParams.ts:171
},
},
})
const field = paths[0].field
const select: Record<string, boolean> = {
_id: true,
}
let joinPath: null | string = null
if (field.type === 'join') {
const relationshipField = getFieldByPath({
fields: collectionConfig.flattenedFields,
path: field.on,
})
if (!relationshipField) {
throw new APIError('Relationship field was not found')
}
let path = relationshipField.localizedPath
if (relationshipField.pathHasLocalized && payload.config.localization) {
path = path.replace('<locale>', locale || payload.config.localization.defaultLocale)
}
select[path] = true
joinPath = path
}
if (joinPath) {
select[joinPath] = true
}
const result = await SubModel.find(subQuery).lean().select(select)
const $in: unknown[] = []View on GitHub (pinned to 00c58b35c0)
Solutions
- Open the collection config and confirm the join field's `on` matches an existing relationship/upload field name/path.
- If the relationship field was renamed, update the join's `on` to the new name.
- Ensure `on` points to a relationship-type field, not a group/array/blocks field.
- Re-run payload's config validation to surface the misconfiguration at boot.
Example fix
// before
{
slug: 'posts',
fields: [
{ name: 'author', type: 'relationship', relationTo: 'users' },
{ name: 'comments', type: 'join', on: 'writer' }, // 'writer' does not exist
],
}
// after
{
slug: 'posts',
fields: [
{ name: 'author', type: 'relationship', relationTo: 'users' },
{ name: 'comments', type: 'join', on: 'author' },
],
} Defensive patterns
Strategy: validation
Validate before calling
import { getFieldByPath } from 'payload'
function assertJoinOnExists(collectionConfig: { flattenedFields: any[] }, joinField: { type: 'join'; on: string }) {
if (joinField.type !== 'join') return
const target = getFieldByPath({ fields: collectionConfig.flattenedFields, path: joinField.on })
if (!target) {
throw new Error(`join field 'on'="${joinField.on}" does not resolve to any field on the collection`)
}
if (target.type !== 'relationship' && target.type !== 'upload') {
throw new Error(`join 'on' must reference a relationship/upload field, got ${target.type}`)
}
} Type guard
function isValidJoinOn(target: unknown): target is { type: 'relationship' | 'upload' } {
return typeof target === 'object' && target !== null &&
['relationship', 'upload'].includes((target as any).type)
} Try / catch
try {
await payload.find({ collection: 'posts', where: { 'comments.text': { like: 'x' } } })
} catch (e) {
if (e instanceof APIError && e.message === 'Relationship field was not found') {
console.error('join field on= points to a missing relationship — fix the collection config')
}
throw e
} Prevention
- Keep join fields' `on` synchronized with the target relationship field name.
- Update `on` whenever the referenced relationship field is renamed.
- Run payload config validation at boot to catch broken join targets early.
When it happens
Trigger: A collection has a join field whose `on` value does not match any relationship field path in flattenedFields — e.g. the referenced relationship field was renamed/removed, or `on` was typed wrong.
Common situations: Renaming a relationship field without updating the join field's `on`; pointing `on` at a non-relationship field (group/array); config imported from another collection where the field does not exist.
Related errors
- Collection with the slug ${collectionSlug} was not found.
- Invalid join field ${field.name}. The config does not have a
- Error: missing MongoDB connection URL.
- Either collection or globalSlug must be passed.
- Localization is not enabled in payload config
AI-assisted analysis of payloadcms/payload@00c58b35c0 (2026-08-12).
Data as JSON: /api/errors/17bf0b439f1b9f4c.
Report an issue: GitHub.