microsoft/semantic-kernel · error · ArgumentException

An orchestration is referencing a node with Id `{listenCondi

Error message

An orchestration is referencing a node with Id `{listenCondition.From}` that does not exist.

What it means

Thrown by WorkflowBuilder when constructing an orchestration edge whose `listen_for.from` Id does not match any registered step and is not the literal sentinel `"_workflow_"` paired with a known input event. The builder resolves the edge source from an internal `_stepBuilders` map keyed by step Id; an unresolved key means the workflow's orchestration references a node that was never added (or was renamed). It is an ArgumentException raised during `AddOrchestrationStepAsync` while translating a declarative workflow into a process graph.

Source

Thrown at dotnet/src/Experimental/Process.Core/Workflow/WorkflowBuilder.cs:278

                // Handle AllOf condition
                edgeBuilder = processBuilder.ListenFor().AllOf(listenCondition.AllOf.Select(c => GetSourceBuilder(c)).ToList());
            }
            else if (!string.IsNullOrWhiteSpace(listenCondition.Event) && !string.IsNullOrWhiteSpace(listenCondition.From))
            {
                // Find the source of the edge, it could either be a step, or an input event.
                if (this._stepBuilders.TryGetValue(listenCondition.From, out ProcessStepBuilder? sourceStepBuilder))
                {
                    // The source is a step.
                    edgeBuilder = sourceStepBuilder.OnEvent(listenCondition.Event);
                }
                else if (listenCondition.From.Equals("_workflow_", StringComparison.OrdinalIgnoreCase) && this._inputEvents.ContainsKey(listenCondition.Event))
                {
                    // The source is an input event.
                    edgeBuilder = processBuilder.OnInputEvent(listenCondition.Event);
                }
                else
                {
                    throw new ArgumentException($"An orchestration is referencing a node with Id `{listenCondition.From}` that does not exist.");
                }
            }
            else
            {
                throw new ArgumentException("A complete listen_for condition is required for orchestration steps.");
            }

            // Now that we have a validated edge source, we can add the then actions
            foreach (var action in thenActions)
            {
                if (action is null || string.IsNullOrWhiteSpace(action.Node))
                {
                    throw new ArgumentException("A complete then action is required for orchestration steps.");
                }

                if (!this._stepBuilders.TryGetValue(action.Node, out ProcessStepBuilder? destinationStepBuilder))
                {
                    if (action.Node.Equals("End", StringComparison.OrdinalIgnoreCase))

View on GitHub (pinned to c028a0c7dc)

Solutions

  1. Open the workflow definition and confirm every `listen_for.from` value exactly matches a step Id declared under `steps` (case-sensitive, no surrounding whitespace).
  2. If the source is a process-level input event, set `from` to `"_workflow_"` and ensure the event name was registered with `OnInputEvent`.
  3. Re-run after any step rename and propagate the new Id to all orchestration `listen_for.from` and `then.node` references.
  4. Add a pre-build validation pass that collects all step Ids and asserts each orchestration `from`/`node` resolves before calling the builder.

Example fix

// before
listen_for:
  from: MyStep
  event: Started
// after (fixed typo against actual step id 'MyStepA')
listen_for:
  from: MyStepA
  event: Started
Defensive patterns

Strategy: validation

Validate before calling

// Before building, confirm every orchestration 'from' resolves to a step or is the input-event sentinel.
var stepIds = new HashSet<string>(workflow.Nodes.Select(n => n.Id), StringComparer.Ordinal);
var inputEvents = new HashSet<string>(declaredInputEvents, StringComparer.Ordinal);
foreach (var step in workflow.Orchestration)
{
    var lc = step.ListenFor;
    if (lc == null) continue;
    var sources = lc.AllOf?.Select(a => a.From).Append(lc.From).Where(f => !string.IsNullOrWhiteSpace(f))
                  ?? new[] { lc.From };
    foreach (var from in sources)
    {
        if (!stepIds.Contains(from)
            && !(from.Equals("_workflow_", StringComparison.OrdinalIgnoreCase) && inputEvents.Contains(lc.Event)))
        {
            throw new InvalidOperationException($"listen_for.from '{from}' does not match any step or declared input event.");
        }
    }
}

Type guard

bool IsValidListenFrom(Workflow wf, string from, string evt) =>
    wf.Nodes.Any(n => string.Equals(n.Id, from, StringComparison.Ordinal))
    || (from.Equals("_workflow_", StringComparison.OrdinalIgnoreCase)
        && wf.InputEvents.Contains(evt, StringComparer.Ordinal));

Try / catch

try { await builder.BuildAsync(); }
catch (ArgumentException ex) when (ex.Message.Contains("does not exist"))
{
    _logger.LogError(ex, "Workflow orchestration references an unknown node; aborting build.");
    throw;
}

Prevention

When it happens

Trigger: Call the workflow builder with an orchestration step whose `listen_for.from` value (a) is not present in the `steps` collection, (b) is `"_workflow_"` but whose `event` is not in `_inputEvents`, or (c) contains a typo/different casing than the step's registered Id. Renaming a step without updating its orchestration `from` also triggers it.

Common situations: Hand-authoring a YAML/declarative workflow and mistyping a node id; refactoring a step and forgetting to update downstream `listen_for` references; using an input event name that was never declared via `process.OnInputEvent(...)`; copy-pasting orchestration blocks between workflows with divergent node ids.

Related errors


AI-assisted analysis of microsoft/semantic-kernel@c028a0c7dc (2026-08-13). Data as JSON: /api/errors/eccf8f3901f36122. Report an issue: GitHub.