-
Notifications
You must be signed in to change notification settings - Fork 3.5k
Description
Describe the Bug
Virtual fields (virtual: true or virtual: "path") show validation errors in the admin UI even though the user cannot edit them. The value is populated server-side (via afterRead hooks, built-in virtual population, or plugin logic), so it's undefined in the form state — causing required/minLength/etc. validators to fail.
This affects all virtual field variants:
virtual: "post.title"— auto-populated by Payloadvirtual: truewithafterReadhook — e.g. computed reading timevirtual: truewithout hooks — e.g. fields populated by plugins or used for type generation only
Reproduction Steps
- Add a virtual field with
required: trueto a collection:
{
name: 'estimatedReadingTime',
type: 'text',
virtual: true,
required: true,
hooks: {
afterRead: [({ data }) => `${Math.ceil((data?.content?.split(/\s+/).length ?? 0) / 200)} min read`],
},
}- Open the admin panel, create or edit a document in that collection
- The field shows "This field is required" — the user cannot resolve this
Expected behavior
Virtual fields should skip client-side validation and be read-only by default, since their value is never user-provided.
Root cause
In packages/payload/src/fields/config/sanitize.ts:273, every data field without an explicit validate gets a default type-based validator — no exception for virtual fields. In packages/ui/src/forms/fieldSchemasToFormState/addFieldStatePromise.ts:216, validation runs on all fields with no virtual check. And RenderFields never auto-sets readOnly for virtual fields.
Workaround
{
name: 'estimatedReadingTime',
type: 'text',
virtual: true,
validate: () => true,
admin: { readOnly: true },
// ...
}Affected areas
- area: core
- area: ui