Xiaobai
Developer · Builder
Building AI engineering systems, developer tools and long-term digital assets at XBSTACK.
About Xiaobai & XBSTACK →
n8n 2.35.3 $json Array Methods Return null: Reproduction and Workaround
In n8n 2.35.3 Edit Fields, $json.data.sort(), splice(), fill() and copyWithin() return null. Compare official 2.34.5 vs 2.35.3 Docker runs and tested copy-first workarounds.
If you upgraded to n8n 2.35.3 and an Edit Fields expression such as:
{{ $json.data.sort() }}
suddenly evaluates to:
null
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) }}
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
The shortest production containment I verified is:
{{ [...$json.data].sort() }}
I also tested copy-first splice(), fill() and copyWithin() on 2.35.3 rather than assuming they would behave like sort().

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"
]
}
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:

| 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:
- The input and node shape are unchanged; only the n8n version changes.
- Not every mutating method is affected;
reverse()works on 2.35.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.

sort()
Before:
{{ $json.data.sort() }}
Use:
{{ [...$json.data].sort() }}
or:
{{ $json.data.slice().sort() }}
Both passed on 2.35.3.
splice()
Before:
{{ $json.data.splice(0, 2) }}
Use:
{{ [...$json.data].splice(0, 2) }}
My 2.35.3 run returned:
["Mango", "Apple"]
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) }}
Use:
{{ [...$json.data].fill("X", 0, 2) }}
Verified 2.35.3 output:
["X", "X", "Kiwi", "Orange", "Blueberry", "Banana", "Peach", "Grape", "Pineapple", "Strawberry"]
copyWithin()
Before:
{{ $json.data.copyWithin(0, 2, 4) }}
Use:
{{ [...$json.data].copyWithin(0, 2, 4) }}
Verified 2.35.3 output:
["Kiwi", "Orange", "Kiwi", "Orange", "Blueberry", "Banana", "Peach", "Grape", "Pineapple", "Strawberry"]
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() }}
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(
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:
- Confirm the runtime is actually 2.35.3, including workers if you run a distributed setup.
- Keep the failing expression and input as a control.
- Change only the array access to a copy-first form and rerun the same item.
- If the copy-first version works, check whether the expression uses
sort,splice,fillorcopyWithindirectly on$json. - Restore the smallest failing point before refactoring the rest of the workflow.
- Audit other workflows for the same direct-mutation pattern.
- 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/copyWithincalls on$json.datareturnnullon 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:
- n8n issue #36540: Regression in 2.35.3: several mutating Array methods on $json return null
- n8n docs: Referencing data in the UI
When upstream ships a confirmed fix, this page should be updated with the affected/fixed version matrix instead of creating another duplicate troubleshooting URL.
Continue through the production automation path
The workflow hub connects self-hosting, queue mode, webhooks, retries, observability and n8n implementation cases into one production-oriented learning path.
More to Explore
Topic hub →AI Engineering Weekly
Production changes, real failures, experiments and new XBSTACK assets.
DISCUSSION
Questions, verification and corrections
Sign in to comment. Every new comment is reviewed before publication; while pending, it is visible only to you and the administrator.