payloadcms/payload · error · APIError
Cannot restore a version of a trashed document (ID: ${parent
Error message
Cannot restore a version of a trashed document (ID: ${parentDocID}). Restore the document first. What it means
Thrown at packages/payload/src/collections/operations/restoreVersion.ts:133 with HTTP 403 (FORBIDDEN) during restoreVersion when the collection has `trash: true` enabled and the parent document is currently soft-deleted (`deletedAt` is set). Restoring a version onto a trashed document is disallowed because the document must first be restored from the trash bin.
Source
Thrown at packages/payload/src/collections/operations/restoreVersion.ts:133
const findOneArgs: FindOneArgs = {
collection: collectionConfig.slug,
locale: 'all',
req,
where: combineQueries({ id: { equals: parentDocID } }, accessResults),
}
// Get the document from the non versioned collection
const doc = await req.payload.db.findOne<TData>(findOneArgs)
if (!doc && !hasWherePolicy) {
throw new NotFound(req.t)
}
if (!doc && hasWherePolicy) {
throw new Forbidden(req.t)
}
if (collectionConfig.trash && doc?.deletedAt) {
throw new APIError(
`Cannot restore a version of a trashed document (ID: ${parentDocID}). Restore the document first.`,
httpStatus.FORBIDDEN,
)
}
// /////////////////////////////////////
// fetch previousDoc
// /////////////////////////////////////
const prevDocWithLocales = await getLatestCollectionVersion({
id: parentDocID,
config: collectionConfig,
payload,
query: findOneArgs,
req,
})
// originalDoc with hoisted localized data
const validationLocale = payload.config.localizationView on GitHub (pinned to 00c58b35c0)
Solutions
- Restore the parent document from trash first (e.g., `payload.update({ collection, id, data: { deletedAt: null } })` with trash enabled), then call restoreVersion.
- Hide the 'Restore version' action in the UI when the parent document is trashed.
- Check `doc.deletedAt` before attempting version restore.
Example fix
// before
await payload.restoreVersion({ collection: 'pages', id: versionId }) // parent is trashed
// after — restore the parent from trash first
await payload.update({ collection: 'pages', id: parentDocID, data: { deletedAt: null } })
await payload.restoreVersion({ collection: 'pages', id: versionId }) Defensive patterns
Strategy: validation
Validate before calling
// Restore the parent from trash before restoring a version
const parent = await payload.findByID({ collection: 'pages', id: parentDocID, overrideAccess: true })
if (parent?.deletedAt) {
// parent is trashed — restore it first
await payload.update({ collection: 'pages', id: parentDocID, data: { deletedAt: null } })
}
await payload.restoreVersion({ collection: 'pages', id: versionId }) Type guard
const isTrashed = (doc: { deletedAt?: string | null } | null): doc is { deletedAt: string } =>
Boolean(doc && typeof doc.deletedAt === 'string' && doc.deletedAt)
if (!isTrashed(parent)) {
await payload.restoreVersion({ collection: 'pages', id: versionId })
} Try / catch
try {
await payload.restoreVersion({ collection: 'pages', id: versionId })
} catch (err) {
if (err instanceof APIError && err.status === 403 && /trashed document/.test(err.message)) {
// restore the parent from trash, then retry restoreVersion
} else throw err
} Prevention
- Hide version Restore actions in the UI when the parent document is trashed.
- Check `doc.deletedAt` before attempting version restore.
- Ensure trash-restore and version-restore flows are presented in the correct order.
When it happens
Trigger: A document was soft-deleted (moved to trash) and a user (or automation) attempts to restore one of its versions before restoring the parent document itself; the admin UI lists versions for a trashed doc and allows the restore action.
Common situations: Trash/soft-delete feature enabled on the collection; orphaned UI state showing version actions for trashed docs; automation that runs restoreVersion without checking trash status.
Related errors
- You are not allowed to perform this action.
- Missing ID of version to restore.
- Not Found
- Collection ${args.collection.config.slug} has disabled bulk
- You are not allowed to perform this action.
AI-assisted analysis of payloadcms/payload@00c58b35c0 (2026-08-12).
Data as JSON: /api/errors/c05d407e75358caf.
Report an issue: GitHub.