payloadcms/payload · error · Error

Cannot provide both collectionSlug and globalSlug

Error message

Cannot provide both collectionSlug and globalSlug

What it means

Argument-contract error from `migratePostgresLocalizeStatus`: a single migration targets either a collection or a global, never both. Passing both is ambiguous because the versions-table name and locales table differ per entity type, so the migration refuses to pick.

Source

Thrown at packages/drizzle/src/postgres/predefinedMigrations/localize-status/index.ts:27

export type LocalizeStatusArgs = {
  collectionSlug?: string
  db: any
  globalSlug?: string
  payload: Payload
  req?: any
  sql: any
}

export async function migratePostgresLocalizeStatus(args: LocalizeStatusArgs): Promise<void> {
  const { collectionSlug, db, globalSlug, payload, req, sql } = args
  const schemaName = db.schemaName ?? 'public'

  if (!collectionSlug && !globalSlug) {
    throw new Error('Either collectionSlug or globalSlug must be provided')
  }

  if (collectionSlug && globalSlug) {
    throw new Error('Cannot provide both collectionSlug and globalSlug')
  }

  const entitySlug = collectionSlug || globalSlug
  // Convert camelCase slugs to snake_case and add version prefix/suffix
  const versionsTable = collectionSlug
    ? `_${toSnakeCase(collectionSlug)}_v`
    : `_${toSnakeCase(globalSlug!)}_v`
  const localesTable = `${versionsTable}_locales`

  if (!payload.config.localization) {
    throw new Error('Localization is not enabled in payload config')
  }

  // Check if versions are enabled on this collection/global
  let entityConfig
  if (collectionSlug) {
    const collection = payload.config.collections.find((c) => c.slug === collectionSlug)
    if (collection) {

View on GitHub (pinned to 00c58b35c0)

Solutions

  1. Supply exactly one slug — `collectionSlug` for a collection or `globalSlug` for a global — and remove the other.
  2. Branch the call site: `if (collectionSlug) migrate({...collectionSlug}) else if (globalSlug) migrate({...globalSlug})`.
  3. Add a runtime assert at the caller to fail fast with a clearer message before reaching the migration.

Example fix

// before
await migratePostgresLocalizeStatus({ collectionSlug: 'posts', globalSlug: 'settings', db, payload, sql })
// after
await migratePostgresLocalizeStatus({ collectionSlug: 'posts', db, payload, sql })
Defensive patterns

Strategy: validation

Validate before calling

const { collectionSlug, globalSlug } = args
if (collectionSlug && globalSlug) {
  throw new Error('Pass only one of collectionSlug or globalSlug')
}
await migratePostgresLocalizeStatus(args)

Type guard

const isExactlyOneSlug = (a): boolean =>
  Boolean(a?.collectionSlug) !== Boolean(a?.globalSlug)

Try / catch

null

Prevention

When it happens

Trigger: Calling `migratePostgresLocalizeStatus({ collectionSlug: 'posts', globalSlug: 'settings', db, payload, sql })` with both slug arguments set.

Common situations: A generic wrapper that always forwards both fields; refactoring a call site from one entity type to the other without clearing the old argument; configuration objects reused across collection and global loops.

Related errors


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