microsoft/semantic-kernel · error · ArgumentException

Workflow nodes are not specified.

Error message

Workflow nodes are not specified.

What it means

Thrown by WorkflowBuilder.BuildProcessAsync when the Workflow has a null or empty Nodes collection. A workflow must declare at least one node to produce a process, so the builder rejects nodeless definitions up front.

Source

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

{
    private readonly Dictionary<string, ProcessStepBuilder> _stepBuilders = [];
    private readonly Dictionary<string, CloudEvent> _inputEvents = [];
    private string? _yaml;

    /// <summary>
    /// Builds a process from a workflow definition.
    /// </summary>
    /// <param name="workflow">An instance of <see cref="Workflow"/>.</param>
    /// <param name="yaml">Workflow definition in YAML format.</param>
    /// <param name="stepTypes">Collection of preloaded step types.</param>
    public async Task<KernelProcess?> BuildProcessAsync(Workflow workflow, string yaml, Dictionary<string, Type>? stepTypes = null)
    {
        this._yaml = yaml;
        var stepBuilders = new Dictionary<string, ProcessStepBuilder>();

        if (workflow.Nodes is null || workflow.Nodes.Count == 0)
        {
            throw new ArgumentException("Workflow nodes are not specified.");
        }

        if (workflow.Inputs is null)
        {
            throw new ArgumentException("Workflow inputs are not specified.");
        }

        // TODO: Process outputs
        // TODO: Process variables

        ProcessBuilder processBuilder = new(workflow.Id, description: workflow.Description, stateType: typeof(ProcessDefaultState));

        if (workflow.Inputs.Events?.CloudEvents is not null)
        {
            foreach (CloudEvent inputEvent in workflow.Inputs.Events.CloudEvents)
            {
                await this.AddInputEventAsync(inputEvent, processBuilder).ConfigureAwait(false);
            }

View on GitHub (pinned to c028a0c7dc)

Solutions

  1. Ensure the workflow YAML/JSON includes a non-empty 'nodes' array before calling BuildProcessAsync.
  2. Validate workflow.Nodes != null && workflow.Nodes.Count > 0 before invoking the builder.
  3. Confirm the deserializer is mapping the nodes field correctly (property name/casing).

Example fix

// before
await builder.BuildProcessAsync(new Workflow { Id = "w1" }, yaml);

// after: populate nodes (or validate first)
if (workflow.Nodes is null || workflow.Nodes.Count == 0) { /* report */ return; }
await builder.BuildProcessAsync(workflow, yaml);
Defensive patterns

Strategy: validation

Validate before calling

if (workflow.Nodes is null || workflow.Nodes.Count == 0)
    throw new ArgumentException("Workflow must contain at least one node.");

Type guard

static bool HasNodes(Workflow w) => w.Nodes is { Count: > 0 };

Try / catch

try { await builder.BuildProcessAsync(workflow, yaml); }
catch (ArgumentException ex) when (ex.Message.Contains("nodes are not specified"))
{ /* prompt for a valid workflow with nodes */ }

Prevention

When it happens

Trigger: Calling BuildProcessAsync with a deserialized Workflow whose Nodes list is null or contains zero entries; passing a freshly constructed empty Workflow; YAML that omits the nodes section.

Common situations: Malformed or partial workflow YAML missing the 'nodes' array; deserialization defaulting Nodes to null; testing with a skeleton Workflow object.

Related errors


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