Skip to content

bug: single-locale publish pairs block/array rows by index, not id #18677

Open

Description

@jhb-dev

Describe the Bug

When a single locale is published with localizeStatus (a non-draft update with one locale), mergeLocalizedData merges the data onto the stored document and pairs array and block rows with the stored rows by index (L100, L155) instead of by id. Each merged row starts as a copy of that stored row (L63), so when the row at an index changes (reorder, insert, delete, block type change):

  1. Reordered array rows swap their other-locale values. Swap two rows and publish en: each row now has the other row's de value. This silently corrupts a locale nobody edited, with the default storage.
  2. A new block inherits the fields of the block previously at its index. Replacing an alpha block (a, alphaLabel) with a beta block (b) stores { blockType: 'beta', b, a, alphaLabel }, persisted with blocksAsJSON: true.

The merge runs after all hooks, so it can't be worked around in a hook.

Suggested fix: match the stored row by id (for blocks also by blockType), falling back to {}, like getExistingRowDoc does. With that change both tests pass:

const existingItem = existingValue?.find((row) => row?.id && row.id === newItem.id) || {}
const blockData = existingValue?.find((row) => row?.id && row.id === newBlockData.id && row.blockType === newBlockData.blockType) || {}

The same bug exists in v4 (4.0.0-beta.0): #18678

Link to the code that reproduces this issue

https://github.com/jhb-software/payload-issue-reproductions/tree/main/single-locale-publish-leaks-stale-row-fields/

Reproduction Steps

  1. Clone this repo and open the single-locale-publish-leaks-stale-row-fields/ directory
  2. pnpm install
  3. pnpm test:int: both tests fail
FAIL  keeps the other locale of an array row with that row when rows are reordered
- Expected: [["second", "Zweite"], ["first", "Erste"]]
+ Received: [["second", "Erste"], ["first", "Zweite"]]

FAIL  does not carry fields of the previous block at the same index into a new block
stored block: { blockType: 'beta', a: 'from alpha', alphaLabel: { en: 'alpha label' }, id: '…', b: 'from beta' }

Which area(s) are affected?

area: core

Environment Info

Relevant Packages:
  payload: 3.90.2
  @payloadcms/db-sqlite: 3.90.2
Node: 22.19.0, pnpm: 11.5.1, darwin arm64
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions