Webhoook problem

Hey everyone, I’m stuck on this n8n workflow and I’m not quite sure what I’m doing wrong.

I have a Webhook → Edit Fields (Set) node. The webhook receives a payment event, and I’m trying to map some values from the incoming payload.

The node keeps failing with:

ExpressionError: Paired item data could not be resolved
Could not resolve paired item data for item 0. The expression references data from a previous node, but the required paired item is missing or has been removed.

I originally thought this was just an expression problem, but the webhook data is definitely there.

The values I’m trying to extract are basically:

order_id
customer_id
amount
status
payment_intent_id

What’s confusing me is that the webhook input actually contains the data, so why is n8n complaining about paired item data?

Hey @Rose_Becky, while you wait for a response, here are some things that might help:

Suggested resources

Automatically matched to your question.

Docs:

Forum:

@daniel_Samuel, @achamm, @barn4k - you’ve helped with similar issues before, can you take a look?

Automatically suggested by n8n’s community bot. It’s a pilot - please share feedback here.

Hey @Rose_Becky, those five fields all use $json, and $json only reads the item coming into the node. It never goes through item pairing, that only happens when an expression reaches back with something like $(‘Webhook’).item. So the paired-item text isn’t the real problem here.

The one to trust is in the output panel: Cannot read properties of undefined (reading ‘metadata’). That means body.data.object wasn’t there on the item that actually ran. With the payload in your input panel these expressions resolve fine, so the run that failed got a different body than the one you’re looking at. Open that run under Executions and check the Webhook output, then either put an If node before Edit Fields that checks {{ $json.body.type }}, or make the fields tolerant:

{{ $json.body.data?.object?.metadata?.order_id }}

What does body look like in the failed execution?

Hi @Rose_Becky, alongside the failed input Deepankar asked for, can you share the Webhook and Edit Fields nodes as JSON? Select both nodes on the canvas, copy with Ctrl/Cmd+C and paste here inside a code block. Remove credentials, headers and customer details first, and include your n8n version.

That will let us check the actual expressions and connections behind the pairing error. If order_id is required downstream, check that it is present before continuing. Optional chaining avoids the property-access error, but doesn’t recover the missing order ID.

Quick fix

In the Edit Fields (Set) node, change your expressions to use .first() or just make sure they are simple $json paths.

Try these:

{{ $json.body.data.object.metadata.order_id }}
{{ $json.body.data.object.metadata.customer_id }}
{{ $json.body.data.object.amount }}
{{ $json.body.data.object.status }}
{{ $json.body.data.object.id }}

If it still complains, use the safer version:

{{ $json.body?.data?.object?.metadata?.order_id }}
{{ $json.body?.data?.object?.metadata?.customer_id }}
{{ $json.body?.data?.object?.amount }}
{{ $json.body?.data?.object?.status }}
{{ $json.body?.data?.object?.id }}

Because your Edit Fields node is immediately after the Webhook, I’d first stop reaching back to another node and map from the current input item.

A paired-item error usually means n8n cannot tell which earlier item the current item should be linked back to.

A quick way to isolate it:

  1. Open the Edit Fields node INPUT and confirm the exact payload shape.
  2. Map the values from that current input instead of referencing a previous node’s specific item.
  3. Pin one redacted webhook payload and test the five fields there.
  4. Only after the mapping is stable, add any branch/merge logic back in.

For a payment workflow I’d also add one reliability check once the expression is fixed: store the provider’s event/payment ID and reject a repeated event before any downstream side effect.

Did this workflow have a Merge/Code/loop node before the screenshot, or is it literally Webhook → Edit Fields in the failing execution?