payloadcms/payload · error · Error
Either collectionSlug or globalSlug must be provided
Error message
Either collectionSlug or globalSlug must be provided
What it means
Argument-contract error from the `migratePostgresLocalizeStatus` predefined migration: the function requires exactly one target entity, so `collectionSlug` and `globalSlug` cannot both be omitted. With neither supplied there is nothing to localize, so the migration refuses to guess.
Source
Thrown at packages/drizzle/src/postgres/predefinedMigrations/localize-status/index.ts:23
import { migrateMainCollectionStatus } from './migrateMainCollection.js'
import { migrateMainGlobalStatus } from './migrateMainGlobal.js'
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/globalView on GitHub (pinned to 00c58b35c0)
Solutions
- Pass exactly one of `collectionSlug` or `globalSlug` identifying the localized, versions-enabled entity to migrate.
- If iterating entities, skip iterations where neither slug applies rather than calling the migration with empty args.
- Guard the call site with an `if (collectionSlug || globalSlug)` check.
Example fix
// before
await migratePostgresLocalizeStatus({ db, payload, req, sql })
// after
await migratePostgresLocalizeStatus({ collectionSlug: 'posts', db, payload, req, sql }) Defensive patterns
Strategy: validation
Validate before calling
function runLocalizeStatus(args) {
const { collectionSlug, globalSlug } = args
if (!collectionSlug && !globalSlug) {
throw new Error('Provide collectionSlug or globalSlug')
}
return migratePostgresLocalizeStatus(args)
} Type guard
const hasEntitySlug = (a): a is { collectionSlug: string } | { globalSlug: string } =>
typeof a?.collectionSlug === 'string' || typeof a?.globalSlug === 'string' Try / catch
null
Prevention
- Wrap predefined migrations in a thin validation layer.
- Always pass exactly one slug argument.
When it happens
Trigger: Invoking `migratePostgresLocalizeStatus({ db, payload, sql })` (or the CLI predefined-migration runner wrapping it) without passing `collectionSlug` or `globalSlug`.
Common situations: Copy-pasting the migration invocation from docs and forgetting the slug argument; building a generic loop that iterates entities but skips empty cases incorrectly; programmatic invocation with a falsy slug variable.
Related errors
- Cannot provide both collectionSlug and globalSlug
- Localization is not enabled in payload config
- ${collectionSlug ? 'Collection' : 'Global'} not found: ${col
- Migration aborted: version__status column not found in ${ver
- Either collectionSlug or globalSlug must be provided
AI-assisted analysis of payloadcms/payload@00c58b35c0 (2026-08-12).
Data as JSON: /api/errors/008c3a6e26ce7f2d.
Report an issue: GitHub.