Skip to content

Virtual field is marked as required in the GraphQL schema #16112

@MurzNN

Description

@MurzNN

Describe the Bug

I'm trying to create a required virtual field that is not required to be set manually during document creation. For this, the Payload Virtual Field feature should suit well, but it doesn't resolve the issue of requiring the setting of the field value manually on the document creation stage.

Marking the field as virtual should also mark it as not required on the creation stage, but still keep it as not null in the document field type (in the payload-types.ts).

Link to the code that reproduces this issue

https://github.com/MurzNN/pl-issue-virtual-field-required

Reproduction Steps

  1. Create a required virtual field and hooks that fill the value, here is an example - field displayName:
export const Users: CollectionConfig = {
  slug: 'users',
  admin: {
    useAsTitle: 'email',
  },
  auth: true,
  fields: [
    // Email added by default
    // Add more fields as needed
    {
      name: 'firstName',
      type: 'text',
      required: true,
    },
    {
      name: 'lastName',
      type: 'text',
      required: false,
    },
    {
      name: 'displayName',
      type: 'text',
      required: true,
      virtual: true,
      hooks: {
        beforeChange: [
          ({ siblingData }) => {
            if (siblingData.firstName && siblingData.lastName) {
              return `${siblingData.firstName} ${siblingData.lastName}`;
            } else {
              return siblingData.firstName;
            }
          }
        ]
      }
    }
  ],
}
  1. See that this field is still required in the GraphQL schema:
type mutationUserInput {
  firstName: String!
  lastName: String
  displayName: String!

that makes it impossible to create a user without filling in the displayName value manually on the creation stage.

Which area(s) are affected?

area: graphql

Environment Info

Binaries:
  Node: 24.13.1
  npm: 11.8.0
  Yarn: 1.22.22
  pnpm: 10.32.1
Relevant Packages:
  payload: 3.80.0
  next: 16.2.1
  @payloadcms/db-sqlite: 3.80.0
  @payloadcms/drizzle: 3.80.0
  @payloadcms/graphql: 3.80.0
  @payloadcms/next/utilities: 3.80.0
  @payloadcms/richtext-lexical: 3.80.0
  @payloadcms/translations: 3.80.0
  @payloadcms/ui/shared: 3.80.0
  react: 19.2.4
  react-dom: 19.2.4
Operating System:
  Platform: linux
  Arch: x64
  Version: #19-Ubuntu SMP PREEMPT_DYNAMIC Fri Mar  6 14:02:58 UTC 2026
  Available memory (MB): 31337
  Available CPU cores: 8

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions