Context
Three separate type coercion bugs surfaced during TOMMY pipeline debugging, each requiring a different fix pattern. All three share the same root cause: n8n’s expression engine silently converts types before nodes evaluate them.The Three Gotchas
1. Array “is not empty” with null default
Symptom: If node crashes with “Wrong type: ” is a string but was expecting an array”. Cause: Code node defaultsforge_tasks to null. The If node condition {{ $json.forge_tasks }} with typeValidation: "strict" and operator “is not empty” (array) receives an empty string (n8n coerces null → '').
Fix: Default to [] in the Code node AND change the If node condition to {{ $json.forge_tasks.length }} with is greater than 0 (number comparison). This sidesteps array type detection entirely.
2. Code node return shape in runOnceForEachItem
Symptom: “Code doesn’t return a single object [item 0]”. Cause: Code node inrunOnceForEachItem mode returns [{json: {...}}] (array-wrapped). This mode expects a bare {json: {...}} — the array wrapper is only valid in runOnceForAllItems mode.
Fix: Remove the [ and ] around the return object.
3. Merge node “empty” output drops all data
Symptom: Downstream Code node receives{} — all context fields (repo, branch, dry_run) are undefined.
Cause: Merge node configured with mode: "chooseBranch" and output: "empty". This signals which branch completed but passes no data. Downstream nodes that expect $input.first().json to contain context get nothing.
Fix: Have downstream Code nodes use $('UpstreamNodeName').first().json to reference data directly instead of relying on $input.