microsoft/semantic-kernel · error · InvalidOperationException
An output target has already been set.
Error message
An output target has already been set.
What it means
Thrown by ProcessStepEdgeBuilder.SendEventTo_Internal when assigning a target to an edge that already has one. Each edge is single-target by design; SendEventTo_Internal returns a fresh builder for fluent chaining, and reusing the already-targeted edge instance is treated as a programming error.
Source
Thrown at dotnet/src/Experimental/Process.Core/ProcessStepEdgeBuilder.cs:118
public ProcessStepEdgeBuilder OnCondition(KernelProcessEdgeCondition condition)
{
Verify.NotNull(condition, nameof(condition));
this.Condition = condition;
return this;
}
/// <summary>
/// Internally overridable implementation: Signals that the output of the source step should be sent to the specified target when the associated event fires.
/// </summary>
/// <param name="target">The output target.</param>
/// <returns>A fresh builder instance for fluid definition</returns>
/// <exception cref="InvalidOperationException"></exception>
/// <exception cref="ArgumentException"></exception>
internal virtual ProcessStepEdgeBuilder SendEventTo_Internal(ProcessTargetBuilder target)
{
if (this.Target is not null)
{
throw new InvalidOperationException("An output target has already been set.");
}
if (target is ProcessFunctionTargetBuilder functionTargetBuilder)
{
if (functionTargetBuilder.Step is ProcessMapBuilder && this.Source is ProcessMapBuilder)
{
throw new ArgumentException($"{nameof(ProcessMapBuilder)} may not target another {nameof(ProcessMapBuilder)}.", nameof(target));
}
}
this.Target = target;
this.Source.LinkTo(this.EventData.EventId, this);
return new ProcessStepEdgeBuilder(this.Source, this.EventData.EventId, this.EventData.EventName, this.EdgeGroupBuilder, this.Condition);
}
/// <summary>
/// Emit the SK step event as an external event with specific topic nameView on GitHub (pinned to c028a0c7dc)
Solutions
- Always chain SendEventTo on the builder returned by the previous call rather than the original edge variable.
- If you need one event to reach multiple targets, define separate edges (one OnEvent/SendEventTo per target) or use an edge group/fan-out mechanism.
- Refactor stored edge references so each is targeted exactly once.
Example fix
// before: same edge targeted twice
var e = step.OnEvent("Done");
e.SendEventTo(a);
e.SendEventTo(b); // throws
// after: chain fresh builders
step.OnEvent("Done").SendEventTo(a);
step.OnEvent("Done").SendEventTo(b); Defensive patterns
Strategy: validation
Validate before calling
if (edge.Target is not null)
throw new InvalidOperationException("Edge already has a target; create a new edge for additional targets."); Type guard
static bool EdgeIsUntargeted(ProcessStepEdgeBuilder e) => e.Target is null;
Try / catch
try { edge.SendEventTo(target); }
catch (InvalidOperationException ex) when (ex.Message.Contains("already been set"))
{ /* use a fresh edge from OnEvent for the new target */ } Prevention
- Treat ProcessStepEdgeBuilder instances as single-use after a target is set.
- Chain on the builder returned by SendEventTo, not the captured variable.
- For fan-out, create one edge per target from the same source event.
When it happens
Trigger: Calling SendEventTo twice on the same ProcessStepEdgeBuilder instance instead of chaining on the returned fresh builder; or capturing and reusing an edge reference after it has been assigned a target.
Common situations: Storing the edge from OnEvent(...) in a variable and calling SendEventTo on it in two branches; refactor that inadvertently double-targets; misusing the fluent API by ignoring the returned builder.
Related errors
- A target and Source must be specified before building the ed
- ProcessMapBuilder may not target another ProcessMapBuilder.
- Failed to build step from agent definition: {node.Id}
- Source step cannot be null.
- No targets found for the specified function and parameter '{
AI-assisted analysis of microsoft/semantic-kernel@c028a0c7dc (2026-08-13).
Data as JSON: /api/errors/d9ca599800acc76c.
Report an issue: GitHub.