DEV Community

Cover image for n8n 2.35.3: Why $json.data.sort() Returns null
xn
xn

Posted on Originally published at xbstack.com

n8n 2.35.3: Why $json.data.sort() Returns null

n8n 2.35.3 $json Array regression reproduction

This is not a generic 'your array is malformed' diagnosis. I ran the same expressions in isolated branches on the official n8n 2.34.5 and 2.35.3 Docker images. Four direct mutating methods regress to null on 2.35.3, while copy-first variants remain usable.

If you upgraded to n8n 2.35.3 and an Edit Fields expression such as:

{{ $json.data.sort() }}
Enter fullscreen mode Exit fullscreen mode

suddenly evaluates to:

null
Enter fullscreen mode Exit fullscreen mode

do not start by rewriting the input JSON. I reproduced the behavior locally with the official n8nio/n8n:2.34.5 and n8nio/n8n:2.35.3 Docker images. The same isolated expressions work on 2.34.5 and fail with null on 2.35.3.

The regression is broader than sort() in this test:

{{ $json.data.sort() }}
{{ $json.data.splice(0, 2) }}
{{ $json.data.fill("X", 0, 2) }}
{{ $json.data.copyWithin(0, 2, 4) }}
Enter fullscreen mode Exit fullscreen mode

All four returned null on 2.35.3. reverse() still worked. Copying the array first also worked.

Do not mutate $json.data directly
Copy first, then mutate the copy
Enter fullscreen mode Exit fullscreen mode

The shortest production containment I verified is:

{{ [...$json.data].sort() }}
Enter fullscreen mode Exit fullscreen mode

I also tested copy-first splice(), fill() and copyWithin() on 2.35.3 rather than assuming they would behave like sort().

n8n 2.35.3 production troubleshooting and upgrade guide: confirm the version, isolate the repro, identify affected methods, apply copy-first mitigation and evaluate rollback

Why this is a version regression, not just a bad expression

n8n issue #36540, opened on August 18, 2026, reports that several mutating Array methods called directly on $json arrays started evaluating to null after an upgrade from 2.34.5 to 2.35.3. The report names the same four affected methods and also notes that reverse() and copy-first sorting still work.

I did not treat the issue report itself as enough evidence. I pulled both official Docker images and executed the same Edit Fields expressions with the same input on both versions.

The comparison environment was:

Item Control Regression
n8n 2.34.5 2.35.3
Docker image n8nio/n8n:2.34.5 n8nio/n8n:2.35.3
Node.js v24.18.0 v24.18.1
Database default SQLite default SQLite
Execution n8n CLI execute n8n CLI execute
Edit Fields same node shape same node shape

Every method was given its own independent branch with this input:

{
  "data": [
    "Mango",
    "Apple",
    "Kiwi",
    "Orange",
    "Blueberry",
    "Banana",
    "Peach",
    "Grape",
    "Pineapple",
    "Strawberry"
  ]
}
Enter fullscreen mode Exit fullscreen mode

That isolation matters. My first combined-field workflow put several mutating expressions in one Edit Fields node. On 2.34.5 those methods really mutate the shared input array, so one field can change what a later field sees. The isolated workflow removes that source of noise and is the authoritative version matrix.

2.34.5 versus 2.35.3

The isolated results:

n8n 2.34.5 versus 2.35.3 Array regression matrix: sort, splice, fill and copyWithin return null on 2.35.3 while reverse remains normal

Expression n8n 2.34.5 n8n 2.35.3
$json.data.sort() sorted array null
$json.data.splice(0, 2) ['Mango','Apple'] null
$json.data.fill('X', 0, 2) filled array null
$json.data.copyWithin(0, 2, 4) mutated array null
$json.data.reverse() works works
[...$json.data].sort() works works
$json.data.slice().sort() works works

Three details narrow the failure surface:

  1. The input and node shape are unchanged; only the n8n version changes.
  2. Not every mutating method is affected; reverse() works on 2.35.3.
  3. Sorting itself still works when it is performed on a copied array.

So the observable boundary is not “JavaScript arrays are broken.” It is that some mutating methods called directly on arrays exposed by $json are handled differently in 2.35.3.

I am deliberately stopping there on root cause. Until upstream maintainers publish a fix or a concrete internal change, it would be speculation to claim that a particular proxy, immutability guard, expression sandbox or serialization path is the cause.

Tested workaround: copy first, then mutate

For a production workflow, I prefer the smallest reversible change first.

n8n 2.35.3 temporary fix: avoid mutating $json.data directly, copy the array first, then call sort, splice, fill or copyWithin

sort()

Before:

{{ $json.data.sort() }}
Enter fullscreen mode Exit fullscreen mode

Use:

{{ [...$json.data].sort() }}
Enter fullscreen mode Exit fullscreen mode

or:

{{ $json.data.slice().sort() }}
Enter fullscreen mode Exit fullscreen mode

Both passed on 2.35.3.

splice()

Before:

{{ $json.data.splice(0, 2) }}
Enter fullscreen mode Exit fullscreen mode

Use:

{{ [...$json.data].splice(0, 2) }}
Enter fullscreen mode Exit fullscreen mode

My 2.35.3 run returned:

["Mango", "Apple"]
Enter fullscreen mode Exit fullscreen mode

Remember that JavaScript splice() returns the removed elements. If your business logic needs the remaining array, changing only the regression workaround does not change that JavaScript semantic.

fill()

Before:

{{ $json.data.fill("X", 0, 2) }}
Enter fullscreen mode Exit fullscreen mode

Use:

{{ [...$json.data].fill("X", 0, 2) }}
Enter fullscreen mode Exit fullscreen mode

Verified 2.35.3 output:

["X", "X", "Kiwi", "Orange", "Blueberry", "Banana", "Peach", "Grape", "Pineapple", "Strawberry"]
Enter fullscreen mode Exit fullscreen mode

copyWithin()

Before:

{{ $json.data.copyWithin(0, 2, 4) }}
Enter fullscreen mode Exit fullscreen mode

Use:

{{ [...$json.data].copyWithin(0, 2, 4) }}
Enter fullscreen mode Exit fullscreen mode

Verified 2.35.3 output:

["Kiwi", "Orange", "Kiwi", "Orange", "Blueberry", "Banana", "Peach", "Grape", "Pineapple", "Strawberry"]
Enter fullscreen mode Exit fullscreen mode

These are runtime results from the same official 2.35.3 image, not untested equivalents inferred from the sort() workaround.

Why copy-first is a better expression boundary anyway

n8n expressions reference data produced by previous nodes. Calling sort(), splice(), fill() or copyWithin() directly on $json.data mixes two concerns: reading the current input and mutating the object that exposes that input.

That can make workflows harder to reason about even without this regression. The combined-field control on 2.34.5 demonstrated the risk directly: one mutating field can change the array that later expressions read.

Copy-first expressions separate the requested result from the input object:

{{ [...$json.data].sort() }}
Enter fullscreen mode Exit fullscreen mode

For a simple string array, that boundary is clear. For arrays of nested objects, remember that spread syntax performs a shallow copy, so deeper mutation still requires its own design decision.

Should you downgrade to 2.34.5?

A rollback is not automatically the safest first move.

If only a handful of Edit Fields expressions are affected, replacing direct mutation with copy-first expressions is usually a smaller and more reversible production change. Search your workflows for calls such as:

.sort(
.splice(
.fill(
.copyWithin(
Enter fullscreen mode Exit fullscreen mode

and focus on expressions that call them directly on $json.xxx arrays.

If a large number of workflows depend on this pattern and you cannot regression-test them quickly, a controlled rollback may be reasonable. But n8n rollback decisions also involve database migrations, other node changes, credentials and your deployment process. Back up the database and workflows and test 2.34.5 before changing production.

A practical 2.35.3 triage sequence

If your symptom matches this article:

  1. Confirm the runtime is actually 2.35.3, including workers if you run a distributed setup.
  2. Keep the failing expression and input as a control.
  3. Change only the array access to a copy-first form and rerun the same item.
  4. If the copy-first version works, check whether the expression uses sort, splice, fill or copyWithin directly on $json.
  5. Restore the smallest failing point before refactoring the rest of the workflow.
  6. Audit other workflows for the same direct-mutation pattern.
  7. When upstream ships a fix, remove the workaround in a test instance first and compare outputs before changing production.

This is not the same n8n bug as yesterday's HTTP Request stream issue

XBSTACK published a separate n8n HTTP Request Raw Body / _readableState troubleshooting article yesterday. The product is the same; the search intent is not.

That issue lives in the HTTP Request Raw Body + Response Format path and exposes a stream-shaped object instead of parsed JSON.

This issue lives in Edit Fields expression evaluation and returns null for several direct $json Array mutations after the 2.35.3 upgrade.

They therefore deserve separate URLs and separate reproduction assets. For broader workflow failure patterns, see the n8n workflow error-handling guide and the Workflow hub.

Evidence boundary and upstream tracking

As of August 19, 2026, I can state the following with local runtime evidence:

  • Upstream issue #36540 reports the same 2.35.3 regression.
  • XBSTACK reproduced the version difference with official 2.34.5 and 2.35.3 Docker images.
  • Direct sort/splice/fill/copyWithin calls on $json.data return null on 2.35.3 in the isolated Edit Fields test.
  • reverse() does not show the same failure.
  • Copy-first versions of all four affected methods pass on 2.35.3.

I am not claiming that a specific internal commit is the root cause, and I am not predicting a fix version before upstream publishes one.

Primary references:

When upstream ships a confirmed fix, this page should be updated with the affected/fixed version matrix instead of creating another duplicate troubleshooting URL.


Canonical article and future updates:
https://www.xbstack.com/en/ai/n8n-2353-json-array-methods-return-null/?utm_source=devto&utm_medium=referral&utm_campaign=n8n_2353_array_null_regression&utm_content=article_body

Public minimal reproduction:
https://github.com/xbstack/n8n-2353-json-array-null-repro

Upstream issue:
https://github.com/n8n-io/n8n/issues/36540

Top comments (0)