payloadcms/payload · error · APIError
Missing ID of document to update.
Error message
Missing ID of document to update.
What it means
Thrown by updateByID when the `id` argument is falsy. The operation cannot target a document without an identifier, so Payload rejects the call early (before access checks or DB reads) with HTTP 400. This guards the Local API `payload.update` and the PATCH/PUT REST routes `/:collection/:id`.
Source
Thrown at packages/payload/src/collections/operations/updateByID.ts:105
overrideLock,
overwriteExistingFiles = false,
populate,
publishAllLocales,
req: {
fallbackLocale,
locale,
payload: { config },
payload,
},
req,
select: incomingSelect,
showHiddenFields,
trash = false,
unpublishAllLocales,
} = args
if (!id) {
throw new APIError('Missing ID of document to update.', httpStatus.BAD_REQUEST)
}
const { data } = args
// /////////////////////////////////////
// Access
// /////////////////////////////////////
const accessResults = !overrideAccess
? await executeAccess(
{ id, slug: collectionConfig.slug, data, req },
collectionConfig.access.update,
)
: true
const hasWherePolicy = hasWhereAccessResult(accessResults)
// /////////////////////////////////////
// Retrieve documentView on GitHub (pinned to 00c58b35c0)
Solutions
- Verify `id` is a non-empty string/number before calling `payload.update` (e.g. `if (!id) throw new Error('id required')`).
- If using the REST API, ensure the request targets `/api/:collection/:id` with a real id in the URL.
- For create-then-update flows, await the create result and read its `id`/`doc.id` before updating.
Example fix
// before
await payload.update({ collection: 'posts', id: req.params.id, data })
// after
if (!req.params.id) throw new Error('Missing document id')
await payload.update({ collection: 'posts', id: req.params.id, data }) Defensive patterns
Strategy: validation
Validate before calling
if (!id || (typeof id !== 'string' && typeof id !== 'number')) {
throw new Error('A non-empty document id is required before update.')
}
await payload.update({ collection, id, data, req }) Type guard
function hasValidId(id: unknown): id is string | number {
return (typeof id === 'string' && id.length > 0) || typeof id === 'number'
} Try / catch
try {
await payload.update({ collection, id, data, req })
} catch (err) {
if (err instanceof APIError && err.status === 400 && /Missing ID/.test(err.message)) {
// caller passed no id — fix the call site
}
throw err
} Prevention
- Always type the caller's id as `string | number` (not optional) at the boundary.
- Validate route params (`req.params.id`) before forwarding to payload.update.
- For create-then-update flows, read `result.doc.id` from the create response first.
When it happens
Trigger: Calling `payload.update({ collection, id: undefined, data })` or `payload.updateByID` without `id`; hitting `PATCH /api/posts` (missing the `:id` URL segment); passing `id: ''` or `id: null` from a route param that did not parse.
Common situations: A REST route or custom endpoint forwards `req.params.id` without validating it; an autosave/client sends an update before the create response returns an id; a script iterates over ids and one row is blank.
Related errors
- Missing 'where' query of documents to update.
- Not Found
- The collection with slug ${String(collectionSlug)} can't be
- Missing ID of version to restore.
- Collection ${args.collection.config.slug} has disabled bulk
AI-assisted analysis of payloadcms/payload@00c58b35c0 (2026-08-12).
Data as JSON: /api/errors/75d54d104e3954f9.
Report an issue: GitHub.