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.
n8n Automation Hub