{"record":{"id":"e0ca945e8af5e6f2","repo":"payloadcms/payload","slug":"collection-args-collection-config-slug-has-disa","errorCode":null,"errorMessage":"Collection ${args.collection.config.slug} has disabled bulk delete","messagePattern":"Collection (.+?) has disabled bulk delete","errorType":"http","errorClass":"APIError","httpStatus":403,"severity":"error","filePath":"packages/payload/src/collections/operations/delete.ts","lineNumber":57,"sourceCode":"  overrideAccess?: boolean\n  overrideLock?: boolean\n  populate?: PopulateType\n  req: PayloadRequest\n  showHiddenFields?: boolean\n  trash?: boolean\n  where: Where\n} & Pick<FindOptions<string, SelectType>, 'select'>\n\nexport const deleteOperation = async <\n  TSlug extends CollectionSlug,\n  TSelect extends SelectFromCollectionSlug<TSlug>,\n>(\n  incomingArgs: Arguments,\n): Promise<BulkOperationResult<TSlug, TSelect>> => {\n  let args = incomingArgs\n\n  if (args.collection.config.disableBulkDelete && !args.overrideAccess) {\n    throw new APIError(`Collection ${args.collection.config.slug} has disabled bulk delete`, 403)\n  }\n\n  try {\n    const shouldCommit = !args.disableTransaction && (await initTransaction(args.req))\n    // /////////////////////////////////////\n    // beforeOperation - Collection\n    // /////////////////////////////////////\n\n    args = await buildBeforeOperation({\n      args,\n      collection: args.collection.config,\n      operation: 'delete',\n      overrideAccess: args.overrideAccess!,\n    })\n\n    const {\n      collection: { config: collectionConfig },\n      depth,","sourceCodeStart":39,"sourceCodeEnd":75,"githubUrl":"https://github.com/payloadcms/payload/blob/00c58b35c0ed348ddc22daabf467b139727214fd/packages/payload/src/collections/operations/delete.ts#L39-L75","documentation":"`deleteOperation` checks `disableBulkDelete` on the collection config; if true and the caller did not pass `overrideAccess`, it throws `APIError` (403). This is a deliberate safety guard preventing accidental mass deletion on collections flagged as bulk-delete-protected.","triggerScenarios":"Calling `payload.delete({ collection, where })` on a collection configured with `disableBulkDelete: true`, without `overrideAccess: true`.","commonSituations":"A cleanup/migration script targeting a protected collection; a UI bulk-action on a guarded collection; forgetting `overrideAccess` in privileged server code.","solutions":["Delete by ID (`payload.deleteByID`) instead of bulk delete, if appropriate.","If this is legitimate privileged work, pass `overrideAccess: true`.","Reconsider whether `disableBulkDelete` should remain true for this collection."],"exampleFix":"// before\nawait payload.delete({ collection: 'orders', where: { status: { equals: 'archived' } } })\n// after (privileged migration only)\nawait payload.delete({ collection: 'orders', where: { status: { equals: 'archived' } }, overrideAccess: true })","handlingStrategy":"validation","validationCode":"function canBulkDelete(collectionConfig, overrideAccess = false) {\n  return !collectionConfig.disableBulkDelete || overrideAccess\n}","typeGuard":"function bulkDeleteAllowed(cfg, overrideAccess): boolean {\n  return overrideAccess || !cfg.disableBulkDelete\n}","tryCatchPattern":"try {\n  await payload.delete({ collection, where })\n} catch (e) {\n  if (e?.statusCode === 403 && /disabled bulk delete/.test(e.message)) {\n    // fall back to per-ID deletes\n  } else throw e\n}","preventionTips":["Check `disableBulkDelete` before issuing bulk deletes.","Prefer `deleteByID` for guarded collections.","Use `overrideAccess` only in trusted scripts."],"tags":["delete","access-control","config","bulk-operations"],"backgroundTag":null,"analyzedSha":"00c58b35c0ed348ddc22daabf467b139727214fd","analyzedAt":"2026-08-12T20:45:03.758Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}