Skip to content

docs: add warning about unique fields with drafts enabled#16096

Open
efe-arv wants to merge 2 commits intopayloadcms:mainfrom
efe-arv:docs/unique-fields-drafts-warning
Open

docs: add warning about unique fields with drafts enabled#16096
efe-arv wants to merge 2 commits intopayloadcms:mainfrom
efe-arv:docs/unique-fields-drafts-warning

Conversation

@efe-arv
Copy link
Copy Markdown

@efe-arv efe-arv commented Mar 30, 2026

What

Adds documentation about a known limitation where unique: true fields on collections with versions.drafts enabled cause silent document creation failures.

The Problem

When a drafts-enabled collection has fields with unique: true, creating new documents can fail silently:

  1. User clicks "Save" or "Publish" on a new document
  2. Payload attempts to write to both the main table and the versions table (_collection_v)
  3. The database-level UNIQUE constraint conflicts during the draft creation process
  4. The Admin UI redirects to ?notFound=<id> with no visible error message

This affects all database adapters (PostgreSQL/Drizzle and MongoDB) and has been reported multiple times:

What This PR Adds

  1. Warning banner in the "Database changes" section of the Drafts docs
  2. New section: "Unique fields with Drafts" with:
    • Clear problem explanation
    • Recommended workaround: replace unique: true with index: true + application-level validate function
    • Complete code example

The Workaround

{
  name: 'slug',
  type: 'text',
  // Use index instead of unique
  index: true,
  validate: async (value, { req, id }) => {
    if (!value) return true
    const existing = await req.payload.find({
      collection: 'my-collection',
      where: {
        slug: { equals: value },
        id: { not_equals: id || 0 },
      },
      limit: 1,
    })
    if (existing.totalDocs > 0) return 'This value is already in use'
    return true
  },
}

Context

We hit this in production on a legal CMS (Payload 3.64.0 + PostgreSQL on Fly.io) with 5,000+ tags. The collection had versions.drafts enabled with unique: true on both name and slug fields. Tag creation was completely broken with no error feedback — just a ?notFound= redirect. Replacing the DB-level unique constraint with an application-level validate function resolved it immediately.

Ideally Payload would handle this gracefully at the framework level (e.g., deferring unique validation for draft documents, or surfacing a clear error), but until then, this documentation helps others avoid the same trap.

@efe-arv efe-arv changed the title docs(versions): add warning about unique fields with drafts enabled docs(payload): add warning about unique fields with drafts enabled Mar 30, 2026
@efe-arv efe-arv changed the title docs(payload): add warning about unique fields with drafts enabled docs: add warning about unique fields with drafts enabled Mar 30, 2026
Document the known limitation where `unique: true` fields on collections
with `versions.drafts` enabled cause silent document creation failures.
The Admin UI redirects to `?notFound=<id>` with no error message.

This has been an open issue since 2022 (payloadcms#953, payloadcms#12628, payloadcms#3576) affecting
users on both MongoDB and PostgreSQL/Drizzle adapters.

Added:
- Warning banner in Database changes section
- New 'Unique fields with Drafts' section with:
  - Problem explanation
  - Application-level uniqueness workaround using validate + index
  - Code example

Relates to payloadcms#953, payloadcms#12628, payloadcms#3576
@efe-arv efe-arv force-pushed the docs/unique-fields-drafts-warning branch from 235e068 to 2c7e905 Compare April 3, 2026 10:04
Copy link
Copy Markdown
Contributor

@jhb-dev jhb-dev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should just be a count operation or at least set depth to 0 and select to {}, to prevent fetching and populating data that is not needed here.

@efe-arv
Copy link
Copy Markdown
Author

efe-arv commented Apr 4, 2026

Good call — updated to use count() instead of find(). No document population needed, just the existence check. Also dropped the redundant limit: 1 since count doesn't paginate.

@efe-arv
Copy link
Copy Markdown
Author

efe-arv commented Apr 4, 2026

Updated to use count() in commit a2f6c2c — no document data is fetched at all, just the total count. The limit: 1 was also removed since count() doesn't paginate. This addresses @jhb-dev's review — both the performance concern and the unnecessary population issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants