payloadcms / payloadcms/payload

cloneDataFromOriginalDoc mangles json array-of-arrays into index-keyed objects on partial update

Open Beginner friendly
#17,475 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Bug
Dominant language
TypeScript
Stars
44.8k
Forks
4.2k
Avg merge
2d 21h
Merged PRs (30d)
53

Description

Describe the Bug

On a partial payload.update / REST PATCH that omits a json field, cloneDataFromOriginalDoc (dist/fields/hooks/beforeChange/cloneDataFromOriginalDoc.js) shallow-clones each array row with {...row}. When the stored value is an array of arrays (e.g. [[lng, lat], ...] coordinate tuples), every inner array is spread into an index-keyed object {"0": lng, "1": lat}.

On a publish operation this trips the field's validate, but draft saves skip validation, so the corrupted shape persists to the database. Downstream consumers that iterate the tuples then crash with TypeError: object is not iterable.

Link to the code that reproduces this issue

n/a (minimal repro below)

Reproduction Steps
  1. Define a collection with a json field, drafts enabled.
  2. Save a document whose json value is an array of arrays, e.g. [[1, 2], [3, 4]].
  3. Run a partial update that omits the json field:
    await payload.update({
      collection: 'things',
      id,
      data: { someOtherField: 'x' }, // json field NOT included
      draft: true,
    })
    
  4. Read the stored value — it is now [{ "0": 1, "1": 2 }, { "0": 3, "1": 4 }] instead of [[1, 2], [3, 4]].

Element order is preserved (so it is recoverable), but the nested arrays are gone.

Expected

Nested arrays inside a json value should be preserved verbatim when the field is omitted from a partial update. A shallow {...row} clone should not be applied to array rows — a structured/deep clone would retain the original shape.

Environment
  • Payload: 3.85.1
  • Database: @payloadcms/db-postgres (json column)

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 in dist/fields/hooks/beforeChange/cloneDataFromOriginalDoc.js and reproduce the partial payload.update or REST PATCH that omits the json field. Verify that array-of-arrays values retain their nested array shape after draft saves, and add regression coverage for the [[1, 2], [3, 4]] example so the stored value is unchanged.

Written by the indexing model from the issue text.

Assessment

Tech stack
postgresql, typescript
Domain
backend, database
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
76/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.