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 · Updated October 13, 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.

Operation shapes side by side

The operations I use most often with this API, written out in full, so the nesting is visible:

// Change a node: fields go inside "updates"
{ "type": "updateNode", "nodeName": "Schedule Trigger",
  "updates": { "name": "Schedule Trigger - 1x Daily",
               "parameters.rule.interval": [{ "triggerAtHour": 7 }] } }

// Add a connection: fields are flat
{ "type": "addConnection", "source": "IF - Ready", "target": "Upload", "sourceOutput": "true" }

// Remove a connection: also flat
{ "type": "removeConnection", "source": "IF - Ready", "target": "Old Node" }

// Rename the workflow: flat
{ "type": "updateName", "name": "WF - Publisher" }

The pattern is easy to remember once seen: anything that changes properties of an existing node goes inside updates, and everything else names its fields directly.

Dotted paths versus whole objects

Inside updates, a dotted key such as "parameters.rule.interval" changes one value and leaves the rest of parameters alone. Passing "parameters": { ... } instead replaces the whole parameters object, and every field you left out is gone. For a one-field change the dotted path is the safer choice. When I do replace a whole object, I first read the node's current parameters and edit that copy.

The same applies to node settings that live outside parameters, such as onError, retryOnFail, maxTries and waitBetweenTries. They are top-level node properties, so the key is just "retryOnFail": true inside updates.

Checking the change actually landed

A successful response only says the request was accepted. After every partial update I read the workflow back and compare the one node I changed. Two things are worth knowing:

Frequently asked questions

What does 'Missing required parameter updates' mean?

The updateNode operation expects every field you want to change inside a nested updates object. Fields placed directly on the operation next to type and nodeId are rejected.

Do addConnection and removeConnection also need an updates object?

No. Connection operations take their fields such as source and target directly on the operation object.

Is it safer to use a dotted path or a full parameters object?

A dotted path such as parameters.url changes one value. A full parameters object replaces everything, and any field you left out is removed.

How do I confirm a partial update worked?

Read the workflow back after the call and compare the changed node. Also make sure no open editor tab saves an older copy over your change.

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.