You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
docs(versions): add warning about unique fields with drafts enabled
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 (#953, #12628, #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 #953, #12628, #3576
Copy file name to clipboardExpand all lines: docs/versions/drafts.mdx
+59Lines changed: 59 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -32,6 +32,10 @@ Collections and Globals both support the same options for configuring drafts. Yo
32
32
33
33
By enabling drafts on a collection or a global, Payload will **automatically inject a new field into your schema** called `_status`. The `_status` field is used internally by Payload to store if a document is set to `draft` or `published`.
34
34
35
+
<Bannertype="warning">
36
+
**`unique` fields and Drafts:** Using `unique: true` on fields in collections with drafts enabled can cause silent failures. When a document is created, Payload writes to both the main collection table and the versions table (`_collectionSlug_v`). Because the initial draft is created with empty or default values before the user fills in the form, a database-level unique constraint will fail on the second document creation — since the first empty-value draft already exists. The Admin UI may redirect to a `?notFound=` URL without showing an error. To work around this, replace `unique: true` with `index: true` and enforce uniqueness at the application level using a custom `validate` function. See [Unique Fields with Drafts](#unique-fields-with-drafts) below.
37
+
</Banner>
38
+
35
39
**Admin UI status indication**
36
40
37
41
Within the Admin UI, if drafts are enabled, a document can be shown with one of three "statuses":
@@ -276,3 +280,58 @@ If a document is published, the Payload Admin UI will be updated to show an "unp
276
280
## Reverting to published
277
281
278
282
If a document is published, and you have made further changes which are saved as a draft, Payload will show a "revert to published" button at the top of the sidebar which will allow you to reject your draft changes and "revert" back to the published state of the document. Your drafts will still be saved, but a new version will be created that will reflect the last published state of the document.
283
+
284
+
## Unique fields with Drafts
285
+
286
+
When using `unique: true` on fields in a collection that has `versions.drafts` enabled, you may encounter silent document creation failures. This is a known limitation ([#953](https://github.com/payloadcms/payload/issues/953), [#12628](https://github.com/payloadcms/payload/issues/12628)).
287
+
288
+
### The problem
289
+
290
+
When Payload creates a new document in a drafts-enabled collection, it writes to both the main collection table and the versions table. The database-level `UNIQUE` constraint on the main table can conflict with the draft creation process — particularly when:
291
+
292
+
- Multiple documents are created before unique field values are filled in (autosave creates rows with empty values)
293
+
- The versions system attempts to write to both tables within the same operation
294
+
295
+
The result is a silent failure where the Admin UI redirects to `?notFound=<id>` instead of showing the newly created document, with no visible error message.
296
+
297
+
### Workaround
298
+
299
+
Replace `unique: true` with `index: true` and enforce uniqueness at the application level using a custom `validate` function:
300
+
301
+
```ts
302
+
const MyCollection:CollectionConfig= {
303
+
slug: 'my-collection',
304
+
versions: {
305
+
drafts: true,
306
+
},
307
+
fields: [
308
+
{
309
+
name: 'slug',
310
+
type: 'text',
311
+
required: true,
312
+
// Use index instead of unique to avoid DB-level constraint conflicts with drafts
313
+
index: true,
314
+
validate: async (value, { req, id }) => {
315
+
if (!value) returntrue
316
+
const existing =awaitreq.payload.find({
317
+
collection: 'my-collection',
318
+
where: {
319
+
slug: { equals: value },
320
+
id: { not_equals: id||0 },
321
+
},
322
+
limit: 1,
323
+
})
324
+
if (existing.totalDocs>0) {
325
+
return'This value is already in use'
326
+
}
327
+
returntrue
328
+
},
329
+
},
330
+
],
331
+
}
332
+
```
333
+
334
+
This approach:
335
+
- Preserves the index for query performance
336
+
- Validates uniqueness before save, providing a clear error message in the Admin UI
337
+
- Avoids the database-level constraint that conflicts with the drafts version system
0 commit comments