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
- Ensure the workflow YAML/JSON includes a non-empty 'nodes' array before calling BuildProcessAsync.
- Validate workflow.Nodes != null && workflow.Nodes.Count > 0 before invoking the builder.
- 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
- Validate the workflow object graph before invoking the builder.
- Author workflow YAML from templates that include a nodes array.
- Unit-test the YAML deserializer to ensure Nodes is populated.
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
- Workflow inputs are not specified.
- Unsupported node type: {node.Type}
- Declarative steps must have an agent defined.
- Failed to build step from agent definition: {node.Id}
- A complete on_complete condition is required for declarative
AI-assisted analysis of microsoft/semantic-kernel@c028a0c7dc (2026-08-13).
Data as JSON: /api/errors/4a7adc6ee5d8041f.
Report an issue: GitHub.