payloadcms / payloadcms/payload

bug: bulk edit drawer drops values from custom field components

Open
#18,116 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

area: ui plugin: seo Bug created-by: Contributor
Dominant language
TypeScript
Stars
44.8k
Forks
4.2k
Avg merge
2d 21h
Merged PRs (30d)
53

Description

Describe the Bug

In the list view's bulk edit drawer ("Edit"), any field rendered by a custom field component silently drops its value. The drawer reports success and bumps updatedAt, but the field is never written.

This affects @payloadcms/plugin-seo out of the box: meta.title, meta.description and meta.image are all custom components, so SEO metadata cannot be bulk edited at all.

Root cause
  1. RenderFields/index.tsx#L88 wraps every field in a <FieldPathContext value={path}> provider. This is what makes custom components work in the normal document edit view.
  2. EditMany/DrawerContent.tsx#L409 calls RenderField directly rather than going through RenderFields, so there is no FieldPathContext provider. It passes path as a prop instead.
  3. RenderField.tsx#L71 short-circuits for custom components: if (CustomField !== undefined) { return CustomField }. CustomField is a pre-rendered element taken from form state, so the path prop is dropped.
  4. MetaTitleComponent.tsx#L62 (and MetaDescriptionComponent.tsx#L69, MetaImageComponent.tsx#L53) calls useField() with no arguments. useField falls back to useFieldPath() (useField/index.tsx#L40), which returns undefined.
  5. setValue therefore writes to the form-state key undefined. On submit, reduceFieldsToValues(fields, true) unflattens that into a top-level "undefined" property.
  6. Server-side "undefined" is not a field in the schema and is discarded, so nothing is written — but the update still succeeds with 200 OK.

The FieldPathContext docblock (RenderFields/context.ts#L6) warns about exactly this: "if you render a field directly, you will need to wrap it with a new FieldPathContext provider." EditMany/DrawerContent.tsx does not. Note that BulkUpload/EditMany/DrawerContent.tsx#L196 does use the provider (with value={undefined}), so the two EditMany implementations diverge here.

This is the custom-component half of the same defect as #10571, which was closed as a duplicate of the group bug #10019 and fixed at the group level in v3.29.0.

Observed behaviour in the reproduction

The input rendered in the drawer gets id="field-undefined", and the PATCH body is:

{ "undefined": "seo only bulk title", "meta": {} }

A plain custom text field (no plugin involved) behaves identically, confirming the bug is in @payloadcms/ui and not in plugin-seo:

{ "undefined": "customtext only" }
Link to the code that reproduces this issue

https://github.com/jhb-software/payload-issue-reproductions/tree/main/bulk-edit-drops-custom-field-values/

Reproduction Steps
  1. Clone this repo and open the bulk-edit-drops-custom-field-values/ directory
  2. pnpm install && cp .env.example .env
  3. pnpm dev and log in at http://localhost:3000/admin as dev@example.com / test (two pages are seeded on first start)
  4. Go to Collections → Pages, tick the select-all checkbox, press Edit
  5. In "Select fields to edit" choose SEO > Title, type any value, press Save
  6. Expected: meta.title is updated on both pages. Actual: the toast says "2 Pages successfully updated" and updatedAt is bumped, but meta.title is unchanged. The input's id is field-undefined and the PATCH body contains {"undefined": "<your value>", "meta": {}}.

Selecting Custom Text instead — a plain custom component defined in this reproduction that calls useField() the same way plugin-seo does — reproduces the same result without any plugin.

Which area(s) are affected?

area: ui
plugin: seo

Environment Info
Binaries:
  Node: 22.19.0
  npm: 10.9.3
  Yarn: N/A
  pnpm: 11.5.1
Relevant Packages:
  payload: 3.88.0
  next: 16.3.4
  @payloadcms/db-sqlite: 3.88.0
  @payloadcms/drizzle: 3.88.0
  @payloadcms/graphql: 3.88.0
  @payloadcms/next/utilities: 3.88.0
  @payloadcms/plugin-seo: 3.88.0
  @payloadcms/richtext-lexical: 3.88.0
  @payloadcms/translations: 3.88.0
  @payloadcms/ui/shared: 3.88.0
  react: 19.2.8
  react-dom: 19.2.8
Operating System:
  Platform: darwin
  Arch: arm64
  Available memory (MB): 24576
  Available CPU cores: 14

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 by comparing the FieldPathContext usage in packages/ui/src/forms/RenderFields/index.tsx with the direct RenderField call in packages/ui/src/elements/EditMany/DrawerContent.tsx. Run the linked bulk-edit reproduction and inspect the custom field components and PATCH body. Done means custom fields retain their paths and bulk editing updates values such as meta.title instead of writing an undefined key.

Written by the indexing model from the issue text.

Assessment

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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.