{"record":{"id":"bfccca97cca3a56b","repo":"microsoft/semantic-kernel","slug":"an-output-target-has-already-been-set","errorCode":null,"errorMessage":"An output target has already been set.","messagePattern":"An output target has already been set\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"dotnet/src/Experimental/Process.Core/ProcessEdgeBuilder.cs","lineNumber":42,"sourceCode":"        this.Source = source;\n    }\n\n    /// <summary>\n    /// Sends the output of the source step to the specified target when the associated event fires.\n    /// </summary>\n    public ProcessEdgeBuilder SendEventTo(ProcessFunctionTargetBuilder target)\n    {\n        return this.SendEventTo(target as ProcessTargetBuilder);\n    }\n\n    /// <summary>\n    /// Sends the output of the source step to the specified target when the associated event fires.\n    /// </summary>\n    public new ProcessEdgeBuilder SendEventTo(ProcessTargetBuilder target)\n    {\n        if (this.Target is not null)\n        {\n            throw new InvalidOperationException(\"An output target has already been set.\");\n        }\n\n        this.Target = target;\n        ProcessStepEdgeBuilder edgeBuilder = new(this.Source, this.EventData.EventId, this.EventData.EventId) { Target = this.Target };\n        this.Source.LinkTo(this.EventData.EventId, edgeBuilder);\n\n        return new ProcessEdgeBuilder(this.Source, this.EventData.EventId);\n    }\n}\n","sourceCodeStart":24,"sourceCodeEnd":52,"githubUrl":"https://github.com/microsoft/semantic-kernel/blob/c028a0c7dc4f0814cdcbaba9d998f187a41197bf/dotnet/src/Experimental/Process.Core/ProcessEdgeBuilder.cs#L24-L52","documentation":"Thrown by ProcessEdgeBuilder.SendEventTo when the Target property is already set. Each ProcessEdgeBuilder represents a single edge from a source event to exactly one target; calling SendEventTo twice on the same edge builder attempts to assign a second target, which is not permitted.","triggerScenarios":"Chaining .SendEventTo(targetA).SendEventTo(targetB) on the same ProcessEdgeBuilder instance — the second SendEventTo call triggers this. The first SendEventTo returns a new ProcessEdgeBuilder, so this only happens if you reuse the original builder object rather than the returned one.","commonSituations":"Saving a ProcessEdgeBuilder reference in a variable and calling SendEventTo on it twice instead of chaining off the return value; misunderstanding the fluent builder pattern where SendEventTo returns a new builder; accidentally calling SendEventTo on a shared edge builder from multiple code paths.","solutions":["Chain SendEventTo calls correctly by using the returned ProcessEdgeBuilder, not re-calling on the same instance.","If you need to send the same event to multiple targets, use the OnInputEvent/ListenFor fluent API to create separate edges for each target.","Avoid storing the ProcessEdgeBuilder in a variable and calling methods on it multiple times; prefer fluent chaining."],"exampleFix":"// before — reusing the same builder variable\nvar edge = step.OnFunction(\"MyFunc\");\nedge.SendEventTo(targetA);\nedge.SendEventTo(targetB); // throws: target already set\n\n// after — chain from the return value\nstep.OnFunction(\"MyFunc\")\n    .SendEventTo(targetA);\nstep.OnFunction(\"MyFunc\")\n    .SendEventTo(targetB); // separate edge for each target","handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never call SendEventTo twice on the same ProcessEdgeBuilder instance — always chain from the return value.","Use fluent chaining: step.OnFunction(\"Func\").SendEventTo(target) rather than storing intermediate builders.","To send the same event to multiple targets, create separate edges via separate OnFunction calls."],"tags":["edge-builder","fluent-api","single-target","dotnet"],"backgroundTag":null,"analyzedSha":"c028a0c7dc4f0814cdcbaba9d998f187a41197bf","analyzedAt":"2026-08-13T13:48:05.040Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}