Skip to content

bug: intermittent TypeError on autosave when saveVersion fails on serverless (Vercel) #16217

@robertjbass

Description

@robertjbass

Description

Autosave PATCH requests intermittently return 500 with a generic {"errors":[{"message":"Something went wrong."}]} response body. The actual error in server logs is TypeError: Cannot read properties of undefined (reading '_status') (or 'lastPublishedAt'), originating in Payload's internal field hook processing.

The 500 response gives no indication of the root cause, making this very difficult to debug. We spent significant time investigating connection pooling, database limits, and middleware before finding the actual source in Vercel function logs.

Reproduction

Config:

const Posts: CollectionConfig = {
  slug: 'posts',
  versions: {
    drafts: {
      autosave: true,
    },
  },
  fields: [
    { name: 'title', type: 'text' },
    { name: 'content', type: 'richText' },
  ],
}

Steps:

  1. Create and publish a document in the admin panel
  2. Open the published document for editing
  3. Edit content so autosave fires PATCH requests
  4. When two autosave PATCHes overlap within the same serverless function invocation, one intermittently returns 500

Environment:

  • Payload 3.81.0 and 3.82.0 (both affected)
  • @payloadcms/db-postgres with Neon (PostgreSQL)
  • Deployed on Vercel (serverless functions)
  • Cannot reproduce on local dev server (single-process, requests are serialized)

Error

The client receives:

{"errors":[{"message":"Something went wrong."}]}

Vercel function logs show the real error:

TypeError: Cannot read properties of undefined (reading '_status')
    at re (node_modules__pnpm_0snv283._.js:155:134460)
    at process.processTicksAndRejections (node:internal/process/task_queues:104:5)
    at async rC (node_modules__pnpm_0snv283._.js:155:142262)
    at async en (node_modules__pnpm_0snv283._.js:155:99079)

Sometimes manifests as:

TypeError: Cannot read properties of undefined (reading 'lastPublishedAt')

Which property triggers the error depends on which field is processed first.

Root Cause

Traced through the Payload source:

  1. saveVersion() catches errors and returns undefined! (saveVersion.ts#L137)
  2. The callers in update operations assign this directly to result without a null check (update.ts#L379)
  3. result (now undefined) is passed as doc to afterRead and afterChange field hooks
  4. Field hooks access doc.id, doc._status, etc. on the undefined value

The transient saveVersion failure is triggered by concurrent autosave requests racing in updateLatestVersion. This is common on Vercel when:

  • Live preview is enabled (the preview iframe polls while autosave fires)
  • afterChange hooks defer work into after() from next/server, keeping the function invocation alive longer and increasing the window for overlapping requests

Vercel logs on failing requests consistently show Peak Concurrency of 2-3 requests on the same function invocation.

Observations

  • Database is healthy (Neon pooler shows plenty of capacity, 0ms wait time, only ~8 actual DB connections)
  • Not related to connection pooling or database limits
  • The failing and succeeding request can be identical, differing only by which Vercel function instance handles them
  • Clicking publish repeatedly eventually succeeds when a request happens to land on an invocation without concurrency pressure

Proposed Fix

PR: #16216

Throw error instead of returning undefined:

packages/payload/src/versions/saveVersion.ts#137

  -    return undefined!
  +    throw err

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions