Skip to content

Commit 3b13867

Browse files
authored
fix: skip validation when trashing documents with empty required fields (#13807)
### What? Skip field validation when trashing documents with empty required fields. ### Why? When trashing a document that was saved as a draft with empty required fields, Payload would run full validation and fail with "The following fields are invalid" errors. This happened because trash operations were treated as regular updates that require full field validation, even though trashing is just a metadata change (setting `deletedAt`) and shouldn't be blocked by content validation issues. ### How? - Modified `skipValidation` logic in `updateDocument()` to skip validation when `deletedAt` is being set in the update data Fixes #13706
1 parent 3acdbf6 commit 3b13867

File tree

4 files changed

+44
-4
lines changed

4 files changed

+44
-4
lines changed

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

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -237,9 +237,11 @@ export const updateDocument = async <
237237
overrideAccess,
238238
req,
239239
skipValidation:
240-
shouldSaveDraft &&
241-
collectionConfig.versions.drafts &&
242-
!collectionConfig.versions.drafts.validate,
240+
(shouldSaveDraft &&
241+
collectionConfig.versions.drafts &&
242+
!collectionConfig.versions.drafts.validate) ||
243+
// Skip validation for trash operations since they're just metadata updates
244+
Boolean(data?.deletedAt),
243245
}
244246

245247
if (publishSpecificLocale) {

test/trash/collections/Posts/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ export const Posts: CollectionConfig = {
1212
{
1313
name: 'title',
1414
type: 'text',
15+
required: true,
1516
},
1617
],
1718
versions: {

test/trash/int.spec.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -648,6 +648,43 @@ describe('trash', () => {
648648
})
649649
})
650650

651+
describe('trashing documents with validation issues', () => {
652+
it('should allow trashing documents with empty required fields (draft scenario)', async () => {
653+
// Create a draft document with empty required field
654+
const draftDoc = await payload.create({
655+
collection: postsSlug,
656+
data: {
657+
title: '', // Empty required field
658+
_status: 'draft',
659+
},
660+
draft: true,
661+
})
662+
663+
expect(draftDoc.title).toBe('')
664+
expect(draftDoc._status).toBe('draft')
665+
666+
// Should be able to trash the document even with empty required field
667+
const trashedDoc = await payload.update({
668+
collection: postsSlug,
669+
id: draftDoc.id,
670+
data: {
671+
deletedAt: new Date().toISOString(),
672+
},
673+
})
674+
675+
expect(trashedDoc.deletedAt).toBeDefined()
676+
expect(trashedDoc.title).toBe('') // Title should still be empty
677+
expect(trashedDoc._status).toBe('draft')
678+
679+
// Clean up
680+
await payload.delete({
681+
collection: postsSlug,
682+
id: draftDoc.id,
683+
trash: true,
684+
})
685+
})
686+
})
687+
651688
describe('deleteByID operation', () => {
652689
it('should throw NotFound error when trying to delete a soft-deleted document w/o trash: true', async () => {
653690
await expect(

test/trash/payload-types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ export interface Page {
134134
*/
135135
export interface Post {
136136
id: string;
137-
title?: string | null;
137+
title: string;
138138
updatedAt: string;
139139
createdAt: string;
140140
deletedAt?: string | null;

0 commit comments

Comments
 (0)