Skip to content

Commit 24b9e13

Browse files
fix: skip validation for unpublish operations with localized required fields (#16120)
## Problem Unpublishing documents with `required: true` + `localized: true` fields fails with a validation error when `localization.fallback: false`. The `UnpublishButton` sends only `{ _status: 'draft' }` with `unpublishAllLocales=true` but no field data, causing `beforeChange` validation to fail on missing required fields. ## Solution Added `unpublishAllLocales` to the `skipValidation` condition in `beforeChange` for both collections and globals — same pattern already used for `isSavingDraft`. ## Why Unpublish is a metadata-only operation (changing `_status`). Field validation is unnecessary since data already exists in the database. Fixes #15651 --------- Co-authored-by: Patrik Kozak <35232443+PatrikKozak@users.noreply.github.com>
1 parent 76f3693 commit 24b9e13

File tree

3 files changed

+51
-2
lines changed

3 files changed

+51
-2
lines changed

packages/payload/src/collections/operations/utilities/update.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,9 @@ export const updateDocument = async <
257257
// only skip validation for drafts when draft validation is false
258258
(isSavingDraft && !hasDraftValidationEnabled(collectionConfig)) ||
259259
// Skip validation for trash operations since they're just metadata updates
260-
(collectionConfig.trash && (Boolean(data?.deletedAt) || isRestoringDraftFromTrash)),
260+
(collectionConfig.trash && (Boolean(data?.deletedAt) || isRestoringDraftFromTrash)) ||
261+
// Skip validation for unpublish operations — they only change _status, not document data
262+
unpublishAllLocales,
261263
}
262264

263265
// /////////////////////////////////////

packages/payload/src/globals/operations/update.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,10 @@ export const updateOperation = async <
253253
global: globalConfig,
254254
operation: 'update' as Operation,
255255
req,
256-
skipValidation: isSavingDraft && !hasDraftValidationEnabled(globalConfig),
256+
skipValidation:
257+
(isSavingDraft && !hasDraftValidationEnabled(globalConfig)) ||
258+
// Skip validation for unpublish operations — they only change _status, not document data
259+
unpublishAllLocales,
257260
}
258261

259262
let result: JsonObject = await beforeChange(beforeChangeArgs)

test/versions/int.spec.ts

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1464,6 +1464,50 @@ describe('Versions', () => {
14641464

14651465
expect(found._status).toBe('draft')
14661466
})
1467+
1468+
it('should unpublish a collection document with localized required fields from a non-default locale', async () => {
1469+
const doc = await payload.create({
1470+
collection: draftCollectionSlug,
1471+
data: {
1472+
_status: 'published',
1473+
description: 'test',
1474+
title: 'unpublish localized test',
1475+
},
1476+
locale: 'en',
1477+
})
1478+
1479+
const unpublished = await payload.update({
1480+
id: doc.id,
1481+
collection: draftCollectionSlug,
1482+
data: { _status: 'draft' },
1483+
locale: 'es',
1484+
unpublishAllLocales: true,
1485+
})
1486+
1487+
expect(unpublished._status).toBe('draft')
1488+
1489+
await payload.delete({ collection: draftCollectionSlug, id: doc.id })
1490+
})
1491+
1492+
it('should unpublish a global with localized required fields from a non-default locale', async () => {
1493+
await payload.updateGlobal({
1494+
slug: draftGlobalSlug,
1495+
data: { _status: 'published', title: 'unpublish global localized test' },
1496+
locale: 'en',
1497+
})
1498+
1499+
const unpublished = await payload.updateGlobal({
1500+
slug: draftGlobalSlug,
1501+
data: { _status: 'draft' },
1502+
fallbackLocale: false,
1503+
locale: 'es',
1504+
unpublishAllLocales: true,
1505+
})
1506+
1507+
expect(unpublished._status).toBe('draft')
1508+
1509+
await cleanupGlobal({ payload, globalSlug: draftGlobalSlug })
1510+
})
14671511
})
14681512

14691513
describe('Draft Types', () => {

0 commit comments

Comments
 (0)