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 document

View on GitHub (pinned to 00c58b35c0)

Solutions

  1. Verify `id` is a non-empty string/number before calling `payload.update` (e.g. `if (!id) throw new Error('id required')`).
  2. If using the REST API, ensure the request targets `/api/:collection/:id` with a real id in the URL.
  3. 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

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


AI-assisted analysis of payloadcms/payload@00c58b35c0 (2026-08-12). Data as JSON: /api/errors/75d54d104e3954f9. Report an issue: GitHub.