Skip to content

Pasting a copied blocks row renders the block blank until page refresh #17375

Open

Description

@DarioSiroki

Describe the Bug

Using a blocks field row's ... menu → Copy Row, then Paste Row onto a row whose field path + row index match the copied row (simplest case: pasting a copied row back over itself; also e.g. layout.0 in one document → layout.0 in another document whose blocks field has the same name), the pasted block's body renders completely blank: the block header stays, but every field inside disappears. In this repro the block contains a single richText field.

The document data is intact — saving works and a full page refresh restores the rendered fields — so it is purely an admin-UI render bug. But for editors it looks like the paste just wiped the block.

After Paste Row:

blank block body after Paste Row

Same document after a full page refresh:

restored after refresh

Root cause

Traced on 3.86.0; the code is identical on 4.0.0-canary.13. All in packages/ui/src/elements/ClipboardAction/mergeFormStateFromClipboard.ts:

  1. On copy, reduceFormStateByPath strips customComponents from the clipboard payload (not serializable) but keeps lastRenderedPath.
  2. On paste, mergeFormStateFromClipboard restores customComponents from existing form state only for array fields — hardcoded undefined for blocks:
    const customComponents = isArray ? formState[newPath]?.customComponents : undefined
  3. On the next form-state request the server decides re-rendering via requiresRender = renderAllFields || !lastRenderedPath || lastRenderedPath !== path || ... (forms/fieldSchemasToFormState/renderField.ts). The pasted entries carry the stale lastRenderedPath from the clipboard; when source and target paths match it equals path, so the server never re-renders the field's components.
  4. The client RichTextField fallback is return null, so the field (label included) renders nothing until a full page load re-renders all fields.

This also explains why the bug looks intermittent: pasting to a different row index or a differently-named blocks field self-heals after the next form-state round-trip (paths mismatch → re-render), while same-path pastes stay blank indefinitely.

Suggested fix

Strip lastRenderedPath (field-level, and row-level inside rows) in reduceFormStateByPath at copy time — verified locally via a patch on 3.86.0: pasted rows then re-render on the next form-state round-trip. (Trade-off: array pastes get one redundant server re-render even though their customComponents survive the merge; alternatives would be restoring customComponents for blocks in the merge, or clearing lastRenderedPath on merged entries at paste time.)

Also reproduces on Payload v4

Same scenario, same result on payload@4.0.0-canary.13 (all @payloadcms/* at 4.0.0-canary.13, next@16.2.6):

blank block body after Paste Row on v4

Link to the code that reproduces this issue

https://github.com/DarioSiroki/payload-paste-row-blank-repro

Reproduction Steps

  1. pnpm install, cp .env.example .env (sqlite file DB, set any PAYLOAD_SECRET), pnpm dev
  2. Open http://localhost:3000/admin, create the first admin user.
  3. Go to Pages → create a new document. Under Layout, click Add Layout → Rich Text Block.
  4. Type hello world into the block's Content rich-text editor and Save.
  5. Reload the edit view and confirm the block renders the Content field with hello world.
  6. Click the block row's ... actions menu → Copy Row.
  7. Open the same ... menu again → Paste Row (pasting onto the same row, layout.0).
  8. Bug: the block body goes blank — only the header (01, Rich Text Block, Untitled) remains; the Content field and its editor are gone.
  9. Refresh the page — the Content field and hello world render again (data was never lost).

Which area(s) are affected?

area: ui

Environment Info

Binaries:
  Node: 24.13.0
  npm: 11.6.2
  Yarn: N/A
  pnpm: 11.1.0
Relevant Packages:
  payload: 3.86.0
  next: 16.2.6
  @payloadcms/db-sqlite: 3.86.0
  @payloadcms/drizzle: 3.86.0
  @payloadcms/graphql: 3.86.0
  @payloadcms/next/utilities: 3.86.0
  @payloadcms/richtext-lexical: 3.86.0
  @payloadcms/translations: 3.86.0
  @payloadcms/ui/shared: 3.86.0
  react: 19.2.6
  react-dom: 19.2.6
Operating System:
  Platform: darwin
  Arch: arm64
  Version: Darwin Kernel Version 25.5.0
  Available memory (MB): 32768
  Available CPU cores: 10

Activity

  1. added
    status: needs-triagePossible bug which hasn't been reproduced yet
    validate-reproductionAuto-added tag on create to tell bot to check recreation URL, removed after check.
    on Jul 17, 2026
  2. added
    area: uiRelated to the admin panel.
    and removed
    validate-reproductionAuto-added tag on create to tell bot to check recreation URL, removed after check.
    on Jul 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area: uiRelated to the admin panel.status: needs-triagePossible bug which hasn't been reproduced yetv3

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions