n8n logon8n Automation Hub
Debugging notes

My n8n API Call Failed With "Missing Required Parameter 'updates'" — Here's the Shape It Actually Wants

Debugging notes · n8n workflow · September 9, 2026

Two different diff-operation types on the same n8n management API accept completely different payload shapes for what looks like the same kind of edit — one flat, one nested. Guessing wrong produces an error that names the missing field but not the structure it belongs in.

Workflow at a glance
  1. Reducing a Schedule Trigger node from three daily firing times down to one meant renaming the node and replacing its rule.interval array in the same call
  2. First attempt: {type: "updateNode", nodeId: "...", name: "...", "parameters.rule.interval": [...]} — fields given directly on the operation object
  3. Result: Missing required parameter 'updates'. The updateNode operation requires an 'updates' object.
  4. Second attempt, same flat shape retried once more out of habit — identical error
  5. Working shape: {type: "updateNode", nodeId: "...", updates: {name: "...", "parameters.rule.interval": [...]}} — every field to change nested one level deeper, inside its own updates key

An easy shape to get wrong by analogy

n8n's partial-workflow-update API accepts a whole family of diff operation types in a single array — addNode, addConnection, removeConnection, updateName, activateWorkflow, and more, including updateNode itself. Several of these take their target fields directly on the operation object: addConnection wants source and target right there, not nested inside anything. Writing updateNode the same way — putting name and a dotted parameters.rule.interval path straight on the operation, next to type and nodeId — is a completely reasonable guess based on how its sibling operations are shaped. It's also wrong.

What the error actually said

The rejected call came back with: Missing required parameter 'updates'. The updateNode operation requires an 'updates' object. Correct structure: {type: "updateNode", nodeId: "abc-123" OR nodeName: "My Node", updates: {name: "New Name", "parameters.url": "https://example.com"}}. That message is unusually good as API errors go — it names the exact missing key and even shows a worked example inline. The mistake on the calling side was pattern-matching against a different operation's shape from memory, then not re-reading the error's own correct-structure example closely enough the first time, and retrying the identical flat payload once more before actually changing anything.

The actual rule

updateNode is the one operation in this API whose target fields live inside a nested updates object rather than flat on the operation itself: {type: "updateNode", nodeId: "...", updates: {name: "...", "parameters.rule.interval": [...]}}. Everything that changes about the node — its display name, any dotted parameter path, disabled, onError, credentials — goes inside that one updates key, never as a sibling of type/nodeId. Connection-oriented operations like addConnection and removeConnection don't follow this pattern at all; their fields genuinely are flat. There isn't a single consistent rule across every operation type in this API — each one has to be checked on its own rather than inferred from a neighboring operation that happens to look similar.

Why the second identical attempt happened at all

The first error's example payload was right there in the response text. Retrying the exact same broken shape a second time, rather than reading that example and adjusting immediately, cost one extra round trip for no reason — a reminder that a documentation-quality error message is only useful if it's actually read on the first failure, not skimmed past on the way to a second attempt at the same guess.

The fix, and the general habit

Wrap every field that should change into the operation's updates object, keeping only type and the node identifier (nodeId or nodeName) outside it: {type: "updateNode", nodeId: "trigger-id", updates: {name: "Schedule Trigger - 1x Daily", "parameters.rule.interval": [{"triggerAtHour": 7}]}}. More generally, when an API supports several operation "types" through one shared array parameter, don't assume they share a payload shape just because they share a family — check each operation's own documented structure before the first call, especially for the ones whose name suggests a direct analogy to one you've already used successfully.

Fighting an API's exact payload shape instead of building the actual automation?

I build and debug production n8n workflows for a living, including the management-API edge cases that don't show up until you're editing something live.