payloadcms / payloadcms/payload

Fields with `admin.condition` are silently hidden in bulk edit

Open
#16,336 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

area: core area: ui created-by: Contributor status: needs-triage
Dominant language
TypeScript
Stars
44.8k
Forks
4.2k
Avg merge
2d 21h
Merged PRs (30d)
53

Description

Describe the Bug

When a field has admin.condition defined, it appears in the Edit dropdown inside the bulk edit drawer — but after selecting it, the field is not rendered. No error or warning is shown. From the user's perspective, bulk edit simply doesn't work for that field.

There is a partial workaround on the user side: if the field that the condition depends on is also selected in the bulk edit drawer, siblingData gets populated and the condition evaluates correctly. However, this forces the user to always edit the dependent field together — which is poor UX — and may cause unintended side effects by updating a field that the user didn't intend to change.

Video showcasing this issue

https://github.com/user-attachments/assets/147c2d29-9c65-484c-9151-35dc22400fd2

Root cause

EditManyDrawerContent initializes DocumentInfoProvider with initialData: {}, so when getFormState builds the form state, siblingData is always {}.

In iterateFields.ts, the condition is evaluated as:

passesCondition = Boolean(
  field.admin.condition(fullData || {}, data || {}, { ... })
)

Since siblingData is {}, any condition that checks sibling field values evaluates to falsepassesCondition = false → the field is not rendered.

reduceFieldOptions (which populates the FieldSelect dropdown) does not check admin.condition, so the field still appears in the dropdown — making the issue invisible until you actually try to use it.

Workarounds

It is technically possible to work around this for individual fields by explicitly handling the undefined case:

For a required select/type field:

// instead of:
condition: (_, siblingData) => siblingData?.type === 'show'

// use:
condition: (_, siblingData) => !siblingData?.type || siblingData?.type === 'show'

Works because type is always explicitly set in real documents, so !siblingData?.type is only ever true in the bulk edit context.

For a boolean/checkbox field:

// instead of:
condition: (_, siblingData) => siblingData?.isEnabled === true

// use:
condition: (_, siblingData) => !(siblingData?.isEnabled === false)

Works because !(undefined === false)true in bulk edit, while still correctly evaluating false when isEnabled is explicitly unchecked.

These workarounds become increasingly fragile as conditions grow in complexity. A condition combining multiple fields:

condition: (_, siblingData) =>
  siblingData?.type === 'premium' &&
  siblingData?.isEnabled === true &&
  siblingData?.tier !== 'basic'

...requires handling undefined for every operand separately, in a way that passes in bulk edit but doesn't break normal form behavior. The result is obscure code that leaks an internal implementation detail (siblingData = {} in bulk edit) into application-level field definitions — something developers shouldn't need to know about.

Expected behavior

admin.condition has no meaningful value in bulk edit context — there is no single document, so sibling field values don't exist. Conditions should be skipped entirely when building form state for bulk edit.

The minimal fix would be to pass skipConditionChecks: true in both getFormState calls inside EditManyDrawerContent (onChange and onFieldSelect). This would require:

  1. Exposing skipConditionChecks in BuildFormStateArgs (packages/payload/src/admin/forms/Form.ts)
  2. Passing it through buildFormStateiterateFields
  3. Setting it in both getFormState calls in packages/ui/src/elements/EditMany/DrawerContent.tsx
Link to the code that reproduces this issue

https://github.com/VeiaG/payload-3-reproductions/tree/bulk-edit-condition-repro

Reproduction Steps
  1. Clone reproduction repo (bulk-edit-condition-repro branch)
  2. Start dev server
  3. Try to bulk edit in bulk-edit-condition.
Which area(s) are affected?

area: core, area: ui

Environment Info
Binaries:
  Node: 22.16.0
  npm: 10.9.2
  Yarn: N/A
  pnpm: 10.19.0
Relevant Packages:
  payload: 3.83.0
  next: 15.4.7
  @payloadcms/db-sqlite: 3.83.0
  @payloadcms/drizzle: 3.83.0
  @payloadcms/email-nodemailer: 3.83.0
  @payloadcms/graphql: 3.83.0
  @payloadcms/live-preview: 3.83.0
  @payloadcms/live-preview-react: 3.83.0
  @payloadcms/next/utilities: 3.83.0
  @payloadcms/payload-cloud: 3.83.0
  @payloadcms/plugin-nested-docs: 3.83.0
  @payloadcms/richtext-lexical: 3.83.0
  @payloadcms/translations: 3.83.0
  @payloadcms/ui/shared: 3.83.0
  react: 19.2.0
  react-dom: 19.2.0
Operating System:
  Platform: darwin
  Arch: arm64
  Version: Darwin Kernel Version 25.2.0: Tue Nov 18 21:09:40 PST 2025; root:xnu-12377.61.12~1/RELEASE_ARM64_T6000
  Available memory (MB): 16384
  Available CPU cores: 10

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with packages/ui/src/elements/EditMany/DrawerContent.tsx and inspect both getFormState calls used by onChange and onFieldSelect. Trace skipConditionChecks through packages/payload/src/admin/forms/Form.ts, buildFormState, and iterateFields.ts. Reproduce with the linked bulk-edit-condition example; done means fields with admin.condition render correctly in bulk edit without requiring dependent fields to be selected.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
frontend
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
65/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.