{"record":{"id":"d839dd4d579651d5","repo":"microsoft/autogen","slug":"from-mismatch-d839dd","errorCode":null,"errorMessage":"From mismatch","messagePattern":"From mismatch","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"dotnet/src/AutoGen.Core/Message/ToolCallMessage.cs","lineNumber":64,"sourceCode":"\n    public ToolCallMessage(string functionName, string functionArgs, string? from = null)\n    {\n        this.From = from;\n        this.ToolCalls = new List<ToolCall> { new ToolCall(functionName, functionArgs) { ToolCallId = functionName } };\n    }\n\n    public ToolCallMessage(ToolCallMessageUpdate update)\n    {\n        this.From = update.From;\n        this.ToolCalls = new List<ToolCall> { new ToolCall(update.FunctionName, update.FunctionArgumentUpdate) };\n    }\n\n    public void Update(ToolCallMessageUpdate update)\n    {\n        // firstly, valid if the update is from the same agent\n        if (update.From != this.From)\n        {\n            throw new System.ArgumentException(\"From mismatch\", nameof(update));\n        }\n\n        // if update.FunctionName exists in the tool calls, update the function arguments\n        var toolCall = this.ToolCalls.FirstOrDefault(tc => tc.FunctionName == update.FunctionName);\n        if (toolCall is not null)\n        {\n            toolCall.FunctionArguments += update.FunctionArgumentUpdate;\n        }\n        else\n        {\n            this.ToolCalls.Add(new ToolCall(update.FunctionName, update.FunctionArgumentUpdate));\n        }\n    }\n\n    public IList<ToolCall> ToolCalls { get; set; }\n\n    public string? From { get; set; }\n","sourceCodeStart":46,"sourceCodeEnd":82,"githubUrl":"https://github.com/microsoft/autogen/blob/027ecf0a379bcc1d09956d46d12d44a3ad9cee14/dotnet/src/AutoGen.Core/Message/ToolCallMessage.cs#L46-L82","documentation":"ToolCallMessage.Update(ToolCallMessageUpdate) first verifies the update comes from the same agent: if update.From != this.From it throws ArgumentException('From mismatch', paramName: update). During function-call streaming, chunks of one tool call must be attributed to a single agent; a chunk from a different sender would corrupt the accumulated arguments. Like TextMessage, null vs non-null From also counts as a mismatch.","triggerScenarios":"Seeded ToolCallMessage with From = null (via new ToolCallMessage(update) where update.From was null) then applying updates with From = \"assistant\"; interleave chunks from two function-calling agents into one accumulator; middleware that stamps From on some chunks only.","commonSituations":"Streaming function-call arguments where the first chunk arrives from raw infrastructure (no agent tag) and subsequent chunks are agent-attributed; group-chat broadcast loops forwarding tool-call updates from multiple agents through shared state.","solutions":["Set From to the agent name on the seed ToolCallMessage and on every ToolCallMessageUpdate.","Key tool-call accumulators by From (and function name) so chunks from different agents stay separate.","If the seed's From is null and updates carry a name, recreate the ToolCallMessage from the first named update.","When broadcasting updates in group chat loops, create a fresh accumulator per agent turn."],"exampleFix":"// before\nvar msg = new ToolCallMessage(new ToolCallMessageUpdate(\"fn\", \"{\") { From = null });\nmsg.Update(new ToolCallMessageUpdate(\"fn\", \"\\\"a\\\":1}\") { From = \"assistant\" }); // throws\n\n// after\nvar msg = new ToolCallMessage(new ToolCallMessageUpdate(\"fn\", \"{\") { From = \"assistant\" });\nmsg.Update(new ToolCallMessageUpdate(\"fn\", \"\\\"a\\\":1}\") { From = \"assistant\" });","handlingStrategy":"validation","validationCode":"if (update.From != msg.From)\n    throw new StreamingException($\"Tool-call chunk From '{update.From}' != message From '{msg.From}'\");\nmsg.Update(update);","typeGuard":"static bool IsSameToolCallSender(ToolCallMessage msg, ToolCallMessageUpdate update) => update.From == msg.From;","tryCatchPattern":"try { toolMsg.Update(update); }\ncatch (ArgumentException ex) when (ex.Message.Contains(\"From mismatch\"))\n{\n    toolMsg = new ToolCallMessage(update); // different sender: start its own accumulation\n}","preventionTips":["Stamp From on every ToolCallMessageUpdate in custom streaming pipelines.","Key tool-call accumulators by (From, FunctionName).","Normalize null-vs-name From mismatches by recreating the seed message with the first named update."],"tags":["autogen","dotnet","message","streaming","tool-call","from-mismatch","argumentexception"],"backgroundTag":null,"analyzedSha":"027ecf0a379bcc1d09956d46d12d44a3ad9cee14","analyzedAt":"2026-08-15T03:38:00.719Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}