payloadcms/payload · warning · Locked
Global document with slug "${globalSlug}" is currently locke
Error message
Global document with slug "${globalSlug}" is currently locked by another user and cannot be modified. What it means
A `Locked` error thrown by `checkDocumentLockStatus` when a global is being modified without holding the lock. Another user lock entry exists for this `globalSlug` with a different `user.value` and an `updatedAt` within the configured lock duration.
Source
Thrown at packages/payload/src/utilities/checkDocumentLockStatus.ts:94
// If there's a locked document, check lock conditions
const lockedDoc = lockedDocumentResult?.docs[0]
if (lockedDoc) {
const lastEditedAt = new Date(lockedDoc?.updatedAt).getTime()
const now = new Date().getTime()
const lockDuration =
typeof lockDocumentsProp === 'object' ? lockDocumentsProp.duration : lockDurationDefault
const lockDurationInMilliseconds = lockDuration * 1000
const currentUserId = req.user?.id
// document is locked by another user and the lock hasn't expired
if (
lockedDoc.user?.value !== currentUserId &&
now - lastEditedAt <= lockDurationInMilliseconds
) {
throw new Locked(finalLockErrorMessage)
}
}
}
// Perform the delete operation regardless of overrideLock status
await payload.db.deleteMany({
collection: lockedDocumentsCollectionSlug,
// Not passing req fails on postgres
req: payload.db.name === 'mongoose' ? undefined : req,
where: lockedDocumentQuery,
})
}
View on GitHub (pinned to 00c58b35c0)
Solutions
- Wait for the lock to expire or have the locking user release it by navigating away / saving.
- Pass `overrideLock: true` in the `updateGlobal` Local API call for automated/forced writes.
- Configure `lockDocuments: false` on the global config if locking is not desired for it.
- Reduce the lock `duration` if locks persist too long.
Example fix
// before
await payload.updateGlobal({
slug: 'siteSettings',
data: { title: 'New Site' },
// blocked by another user active lock
})
// after
await payload.updateGlobal({
slug: 'siteSettings',
data: { title: 'New Site' },
overrideLock: true,
}) Defensive patterns
Strategy: try-catch
Validate before calling
// Before updating a global, check for active locks
const locks = await payload.find({
collection: 'payload-locked-documents',
where: { globalSlug: { equals: globalSlug } },
depth: 1,
})
const lock = locks.docs[0]
if (lock && lock.user?.value !== currentUserId && Date.now() - new Date(lock.updatedAt).getTime() < duration * 1000) {
throw new Error('Global is locked')
} Try / catch
try {
await payload.updateGlobal({ slug: globalSlug, data, overrideLock: false })
} catch (e) {
if (e.name === 'Locked') {
// wait, notify user, or use overrideLock: true for automated writes
} else throw e
} Prevention
- For automated global writes, pass overrideLock: true.
- Set lockDocuments: false on globals that are exclusively automated.
- Show lock status in the admin UI for collaborative global editing.
- Use a reasonable lock duration to avoid stale locks.
When it happens
Trigger: A write to a global (e.g. `payload.updateGlobal`) where `overrideLock` is `false`, the global `lockDocuments` is not `false`, and a recent lock entry exists in the `locked-documents` collection for this `globalSlug` owned by a different user.
Common situations: Two admin users editing the same global (e.g. site settings) concurrently; a stale lock from a user who closed the browser tab; automated global updates colliding with manual admin edits; long lock durations preventing timely automated writes.
Related errors
- Document with ID ${id} is currently locked by another user a
- ${sanitizedConfig.admin!.user} is not a valid admin user col
- Join fields cannot be added to arrays, blocks or globals.
- Not Found
- Not Found
AI-assisted analysis of payloadcms/payload@00c58b35c0 (2026-08-12).
Data as JSON: /api/errors/ef4f8fe8e5f31330.
Report an issue: GitHub.