Portal Community
PropertyValue
Directive nameoutput
Required isolation levelSafe
ProjectNodeData.Services
Data sourceINodeExecutionData.GetNodeOutput(nodeKey)
Path structure$output.NodeKey.fieldPath

Syntax

Read a field from a named upstream node
{@ $output.NodeKey.fieldName }
Nested path
{@ $output.FetchCustomer.profile.billing.email }
Entire node output as JSON
{@ $output.ParseInvoice @json }
NodeKey is the workflow node's unique key The first path segment must exactly match the key property of the upstream node definition (e.g., FetchCustomer, ParseInvoice, HttpCall_1). Keys are case-sensitive.

Complex Scenarios

Scenario 1 — Merging Outputs from Two Parallel Nodes

After a ParallelFork, two branches fetch enrichment data. A subsequent merge node combines them:

// Branch A node key: "FetchCRM"   — fetches customer CRM data
// Branch B node key: "FetchERP"   — fetches customer ERP data
// Merge node builds combined payload:

{
  "customerId": "{@ $output.FetchCRM.id }",
  "crmEmail":   "{@ $output.FetchCRM.email }",
  "erpAccount": "{@ $output.FetchERP.accountCode }",
  "erpCredit":  {@ $output.FetchERP.creditLimit }
}

Scenario 2 — HTTP Response Status Check

Read the HTTP status code from a previous HTTP node to decide on retry logic:

// IfCondition: check if the previous HTTP call succeeded
{@ $js`
const status = context.output.PostToERP.statusCode;
return status >= 200 && status < 300;
` }
// true → continue, false → route to retry/error branch

// Alternatively, read the body field from an HTTP response
{@ $output.PostToERP.body.transactionId }

Scenario 3 — Chaining Node Outputs Through a Pipeline

A 4-node pipeline where each node enriches the previous output:

Node 1 (ValidateInput)  → outputs: { "cleaned": {...} }
Node 2 (EnrichFromCRM)  → outputs: { "enriched": {...} }
Node 3 (CalculateTax)   → outputs: { "taxAmount": 450 }
Node 4 (BuildPayload)   → assembles all three:

{
  "cleanedData": {@ $output.ValidateInput.cleaned @json },
  "crmData":     {@ $output.EnrichFromCRM.enriched @json },
  "tax":         {@ $output.CalculateTax.taxAmount }
}

Scenario 4 — Dynamic Error Reporting

After a TryCatch block, read the error from the failed node to build a meaningful alert:

// CatchBlock node — builds error notification
Error in workflow "{@ $flow.current.name }":
Node {@ $exec.nodeKey } failed with: {@ $output.FailedNode.error.message @default:Unknown error }
Execution: {@ $exec.executionId }
Triggered by: {@ $ctx.user.email } at {@ $ctx.now }

Scenario 5 — Output from Webhook Trigger Node

A webhook trigger node captures the incoming request. Downstream nodes read the webhook payload:

// Webhook trigger node key: "WebhookReceive"
// Its output: { "headers": {...}, "body": {...}, "query": {...} }

// Read Authorization header
{@ $output.WebhookReceive.headers.Authorization }

// Read event type from body
{@ $output.WebhookReceive.body.event }

// Read query parameter
{@ $output.WebhookReceive.query.apiVersion @default:v1 }

Scenario 6 — Comparing Two Node Outputs

Use JavaScript to compare outputs from two independent nodes:

// Node "GetCurrentPrice" and "GetHistoricalPrice" run in parallel
// Decision node checks if price changed significantly:
{@ $js`
const current    = context.output.GetCurrentPrice.price;
const historical = context.output.GetHistoricalPrice.price;
const pctChange  = Math.abs((current - historical) / historical * 100);
return pctChange > 5 ? 'significant' : 'normal';
` }
// Routes to "AlertTeam" branch if > 5% change

Common Errors

ErrorCauseFix
PathNotFound: MyNodeKeyNode key typo or node hasn't executed yetCheck node key spelling (case-sensitive); ensure node is upstream in the same thread
PathNotFound: MyNode.body.fieldHTTP response body not parsed as JSONEnable JSON response parsing in the HttpRequest node settings
Stale value from previous runReading output from a node in a different thread$output is scoped to the current thread; use $var to pass data across threads