Skip to content

Commit dc793d1

Browse files
authored
fix: ValidationError error message when label is a function (#11904)
Fixes #11901 Previously, when `ValidationError` `errors.path` was referring to a field with `label` defined as a function, the error message was generated with `[object Object]`. Now, we call that function instead. Since the `i18n` argument is required for `StaticLabel`, this PR introduces so you can pass a partial `req` to `ValidationError` from which we thread `req.i18n` to the label args.
1 parent f9c73ad commit dc793d1

File tree

3 files changed

+36
-1
lines changed

3 files changed

+36
-1
lines changed

packages/drizzle/src/upsertRow/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,7 @@ export const upsertRow = async <T extends Record<string, unknown> | TypeWithID>(
423423
path: fieldName,
424424
},
425425
],
426+
req,
426427
},
427428
req?.t,
428429
)

packages/payload/src/errors/ValidationError.ts

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { en } from '@payloadcms/translations/languages/en'
44
import { status as httpStatus } from 'http-status'
55

66
import type { LabelFunction, StaticLabel } from '../config/types.js'
7+
import type { PayloadRequest } from '../types/index.js'
78

89
import { APIError } from './APIError.js'
910

@@ -28,6 +29,10 @@ export class ValidationError extends APIError<{
2829
errors: ValidationFieldError[]
2930
global?: string
3031
id?: number | string
32+
/**
33+
* req needs to be passed through (if you have one) in order to resolve label functions that may be part of the errors array
34+
*/
35+
req?: Partial<PayloadRequest>
3136
},
3237
t?: TFunction,
3338
) {
@@ -37,8 +42,36 @@ export class ValidationError extends APIError<{
3742
? en.translations.error.followingFieldsInvalid_one
3843
: en.translations.error.followingFieldsInvalid_other
3944

45+
const req = results.req
46+
// delete to avoid logging the whole req
47+
delete results['req']
48+
4049
super(
41-
`${message} ${results.errors.map((f) => f.label || f.path).join(', ')}`,
50+
`${message} ${results.errors
51+
.map((f) => {
52+
if (f.label) {
53+
if (typeof f.label === 'function') {
54+
if (!req || !req.i18n || !req.t) {
55+
return f.path
56+
}
57+
58+
return f.label({ i18n: req.i18n, t: req.t })
59+
}
60+
61+
if (typeof f.label === 'object') {
62+
if (req?.i18n?.language) {
63+
return f.label[req.i18n.language]
64+
}
65+
66+
return f.label[Object.keys(f.label)[0]]
67+
}
68+
69+
return f.label
70+
}
71+
72+
return f.path
73+
})
74+
.join(', ')}`,
4275
httpStatus.BAD_REQUEST,
4376
results,
4477
)

packages/payload/src/fields/hooks/beforeChange/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ export const beforeChange = async <T extends JsonObject>({
7777
collection: collection?.slug,
7878
errors,
7979
global: global?.slug,
80+
req,
8081
},
8182
req.t,
8283
)

0 commit comments

Comments
 (0)