payloadcms/payload · error · APIError
Either collection or globalSlug must be passed.
Error message
Either collection or globalSlug must be passed.
What it means
Thrown by the Drizzle `deleteVersions` when neither `collectionSlug` nor `globalSlug` is supplied — both the global branch and the collection branch are skipped, so the method cannot determine which versions table to delete from and aborts. This is primarily an internal-contract violation since `deleteVersions` is an adapter method, not a public API.
Source
Thrown at packages/drizzle/src/deleteVersions.ts:32
this: DrizzleAdapter,
{ collection: collectionSlug, globalSlug, locale, req, where: where },
) {
let tableName: string
let fields: FlattenedField[]
if (globalSlug) {
const globalConfig = this.payload.globals.config.find(({ slug }) => slug === globalSlug)
tableName = this.tableNameMap.get(`_${toSnakeCase(globalSlug)}${this.versionsSuffix}`)
fields = buildVersionGlobalFields(this.payload.config, globalConfig, true)
} else if (collectionSlug) {
const collectionConfig: SanitizedCollectionConfig =
this.payload.collections[collectionSlug].config
tableName = this.tableNameMap.get(
`_${toSnakeCase(collectionConfig.slug)}${this.versionsSuffix}`,
)
fields = buildVersionCollectionFields(this.payload.config, collectionConfig, true)
} else {
throw new APIError('Either collection or globalSlug must be passed.')
}
const { docs } = await findMany({
adapter: this,
fields,
joins: false,
limit: 0,
locale,
page: 1,
pagination: false,
req,
tableName,
where,
})
const ids = []
docs.forEach((doc) => {View on GitHub (pinned to 00c58b35c0)
Solutions
- Always pass `collectionSlug` or `globalSlug` when calling `deleteVersions`.
- Prefer the public API (`payload.deleteVersions({ collection })` / `{ global }`) over adapter internals.
- If hitting this via a public API path, report it as a bug with a reproduction.
- In custom subclasses, forward both slugs from the caller.
Example fix
// before
await adapter.deleteVersions({ req }) // no slug
// after
await payload.deleteVersions({ collection: 'posts', id, req }) Defensive patterns
Strategy: validation
Validate before calling
function assertDeleteVersionsTarget(args) {
if (!args.collectionSlug && !args.globalSlug)
throw new Error('deleteVersions requires collectionSlug or globalSlug')
} Type guard
const hasDeleteTarget = (a) => Boolean(a?.collectionSlug) || Boolean(a?.globalSlug)
Try / catch
try { await adapter.deleteVersions(args) }
catch (e) { if (/Either collection or globalSlug/.test(e.message)) throw new Error('Caller must specify a target') else throw e } Prevention
- Call the public API (payload.deleteVersions) rather than adapter internals.
- In adapter subclasses, always forward collectionSlug/globalSlug.
- Treat hitting this via a public path as a bug to report with a repro.
When it happens
Trigger: An internal/programmatic call to the adapter's `deleteVersions` without specifying a target slug — e.g. a custom adapter subclass, a fork calling private methods, or a regression in Payload internals that drops the slug.
Common situations: Custom adapter subclassing that overrides/wraps deleteVersions; calling adapter internals directly instead of the public API; an upgrade regression that stopped forwarding the slug.
Related errors
- Fields are not initialized.
- ERROR: Failed to retrieve collection version model with the
- ERROR: Failed to retrieve global version model with the slug
- The global with slug ${String(globalSlug)} can't be found.
- The global with slug ${String(globalSlug)} can't be found.
AI-assisted analysis of payloadcms/payload@00c58b35c0 (2026-08-12).
Data as JSON: /api/errors/f49c475d00905ff3.
Report an issue: GitHub.