payloadcms/payload · error · InvalidFieldRelationship

Field ${field.label} has invalid relationship '${relationshi

Error message

Field ${field.label} has invalid relationship '${relationship}'.

What it means

A relationship/upload field's `relationTo` slug is not in the `validRelationships` allow-list passed during sanitization. `validRelationships` is non-null when Payload restricts which collections a relationship may target (notably for relationships inside arrays/blocks/uploads and during cross-collection validation), so any target outside that list is rejected.

Source

Thrown at packages/payload/src/fields/config/sanitize.ts:264

      parentIsLocalized,
      polymorphicJoins,
    })
  }

  // Relationship/upload validation
  if (field.type === 'relationship' || field.type === 'upload') {
    if (Array.isArray(field.relationTo) && field.relationTo.length === 0) {
      throw new Error(
        `Field "${field.name}" of type "${field.type}" has an empty relationTo array. At least one collection must be specified.`,
      )
    }

    if (validRelationships) {
      const relationships = Array.isArray(field.relationTo) ? field.relationTo : [field.relationTo]

      relationships.forEach((relationship: string) => {
        if (!validRelationships.includes(relationship)) {
          throw new InvalidFieldRelationship(field, relationship)
        }
      })
    }
  }

  // Upload isSortable default
  if (field.type === 'upload') {
    if (!field.admin || !('isSortable' in field.admin)) {
      field.admin = {
        isSortable: true,
        ...field.admin,
      }
    }
  }

  // Slug field: apply defaults, attach generation hook, expose slugify to the server fn.
  if (field.type === 'slug') {
    const useAsSlug = field.useAsSlug

View on GitHub (pinned to 00c58b35c0)

Solutions

  1. Correct the `relationTo` slug so it matches an existing, allowed collection.
  2. If the collection genuinely should be allowed, review why `validRelationships` is scoped (e.g. upload-file relationships) and adjust the container config.
  3. Ensure the referenced collection is declared earlier or that sanitization order resolves it.

Example fix

// before (Posts collection does not exist or is not allowed here)
{ type: 'relationship', name: 'post', relationTo: 'Post' }
// after
{ type: 'relationship', name: 'post', relationTo: 'posts' }
Defensive patterns

Strategy: validation

Validate before calling

function assertRelationshipsValid(config) {
  const allSlugs = new Set(config.collections.map(c => c.slug))
  const problems = []
  function walk(fields) {
    for (const f of fields) {
      if (f?.type === 'relationship' || f?.type === 'upload') {
        const rels = Array.isArray(f.relationTo) ? f.relationTo : [f.relationTo]
        for (const r of rels) if (!allSlugs.has(r)) problems.push(`${f.name} -> ${r}`)
      }
      if (Array.isArray(f?.fields)) walk(f.fields)
      if (Array.isArray(f?.blocks)) for (const b of f.blocks) if (b?.fields) walk(b.fields)
    }
  }
  for (const c of config.collections) walk(c.fields)
  return problems
}

Type guard

function relationToExists(f: any, knownSlugs: Set<string>): boolean {
  if (f?.type !== 'relationship' && f?.type !== 'upload') return true
  const rels = Array.isArray(f.relationTo) ? f.relationTo : [f.relationTo]
  return rels.every((r: string) => knownSlugs.has(r))
}

Try / catch

try {
  await payload.init({ config })
} catch (err) {
  if (err?.name === 'InvalidFieldRelationship' || /invalid relationship/i.test(err?.message ?? '')) {
    console.error('Bad relationship target:', err?.data)
  }
  throw err
}

Prevention

When it happens

Trigger: A relationship field nested in an array/block pointing to a collection not allowed in that context; a relationship whose `relationTo` slug has a typo or references a not-yet-defined collection when validRelationships is scoped.

Common situations: Renaming a collection without updating references; pointing an array's relationship at a collection that isn't in the allowed set for that container; copy-pasting a relationship across configs with different collection sets.

Related errors


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