Portal Community

When to Return Skip

NodeExecutionResult.Skip() signals that the node completed without producing meaningful data and does not wish to route to any downstream node. Common use cases:

public class IdempotencyCheckExecutor : BaseNodeExecutor
{
    public override async Task<NodeExecutionResult> ExecuteAsync(NodeExecutionContext ctx)
    {
        var key = ctx.GetInput<string>("idempotencyKey");
        if (await _cache.ExistsAsync(key))
        {
            // Already processed — skip silently, do not continue
            return NodeExecutionResult.Skip();
        }
        await _cache.SetAsync(key);
        return NodeExecutionResult.Success(new { processed = true });
    }
}

What Skip Does to the Graph

When Skip() is returned:

  1. ExecutionMemory.nodeOutputs[nodeId] is set to null
  2. No edges from any port are followed — execution stops at this node for this branch
  3. If the node is part of a join, the join gateway treats this branch as completed with null
  4. The node status in the observer panel shows as "Skipped" (gray icon)

Null Output vs. Skip

Return ValueMemory EntryRoutingObserver State
Skip()nullNo edges followedSkipped
Success(null)nullMain port edges followedCompleted
Success(new {}){}Main port edges followedCompleted
Key distinction: Success(null) still routes downstream via the main port — it just passes null as the data. Skip() halts routing entirely. Use Skip() only when you intentionally want to stop this execution branch.

Accessing Null Output Safely

If a downstream node references a skipped node's output, it receives null. Guard with optional chaining:

// idempotencyCheck was skipped — its output is null
$output.idempotencyCheck?.processed ?? false   // → false (safe)
$output.idempotencyCheck.processed             // → runtime error: cannot read property of null

Fire-and-Forget Side-Effect Nodes

Nodes that perform side effects (send a log event, increment a counter, post to an analytics service) but have no downstream consumers should return Success(new { ok = true }) rather than Skip(). This records that the node ran and provides a completion signal for join gateways:

// Audit logger — fire-and-forget style
return NodeExecutionResult.Success(new
{
    ok = true,
    auditId = auditEntry.Id,
    timestamp = DateTimeOffset.UtcNow
});