{"record":{"id":"1fa7eb0fbdbb443d","repo":"microsoft/semantic-kernel","slug":"unable-to-transform-output-to-typeof-toutput","errorCode":null,"errorMessage":"Unable to transform output to {typeof(TOutput)}.","messagePattern":"Unable to transform output to (.+?)\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"dotnet/src/Agents/Orchestration/Transforms/DefaultTransforms.cs","lineNumber":39,"sourceCode":"\n        IEnumerable<ChatMessageContent> TransformInput() =>\n            input switch\n            {\n                IEnumerable<ChatMessageContent> messages => messages,\n                ChatMessageContent message => [message],\n                string text => [new ChatMessageContent(AuthorRole.User, text)],\n                _ => [new ChatMessageContent(AuthorRole.User, JsonSerializer.Serialize(input))]\n            };\n    }\n\n    public static ValueTask<TOutput> ToOutput<TOutput>(IList<ChatMessageContent> result, CancellationToken cancellationToken = default)\n    {\n        bool isSingleResult = result.Count == 1;\n\n        TOutput output =\n            GetDefaultOutput() ??\n            GetObjectOutput() ??\n            throw new InvalidOperationException($\"Unable to transform output to {typeof(TOutput)}.\");\n\n        return new ValueTask<TOutput>(output);\n\n        TOutput? GetObjectOutput()\n        {\n            if (!isSingleResult)\n            {\n                return default;\n            }\n\n            try\n            {\n                return JsonSerializer.Deserialize<TOutput>(result[0].Content ?? string.Empty);\n            }\n            catch (JsonException)\n            {\n                return default;\n            }","sourceCodeStart":21,"sourceCodeEnd":57,"githubUrl":"https://github.com/microsoft/semantic-kernel/blob/c028a0c7dc4f0814cdcbaba9d998f187a41197bf/dotnet/src/Agents/Orchestration/Transforms/DefaultTransforms.cs#L21-L57","documentation":"DefaultTransforms.ToOutput<TOutput> coerces an IList<ChatMessageContent> into TOutput by trying, in order: direct list assignment, a single ChatMessageContent, a single string, then JSON deserialization of result[0].Content. If every strategy returns null (and the JSON Deserialize either returns null or throws JsonException which is swallowed to null), it throws InvalidOperationException. So the throw means TOutput is neither assignable from the list/ChatMessageContent/string nor deserializable from the message content.","triggerScenarios":"Declaring the orchestration's TOutput as a complex POCO while the agent returns plain prose (non-JSON); result.Count != 1 combined with a TOutput that is not IList<ChatMessageContent>; result[0].Content being null or malformed JSON when TOutput is a class/struct.","commonSituations":"Mismatch between the agent's natural-language output and a structured TOutput; forgetting to instruct the model to emit JSON; using a custom output transform incorrectly so the default transform is still applied.","solutions":["Make TOutput match what the agent actually produces (string or ChatMessageContent or IList<ChatMessageContent>).","If you need a structured type, ensure the agent emits valid JSON for that type (prompt/instructions or a structured-output transform).","Supply a custom orchestration output transform so the default ToOutput path is not used."],"exampleFix":"// before: agent returns prose, but TOutput is a class\nvar orch = new MyOrchestration<string, SummaryPoco>(agent);\n\n// after: align TOutput to actual output\nvar orch = new MyOrchestration<string, string>(agent);\n// or instruct the agent to return JSON matching SummaryPoco and keep TOutput=SummaryPoco","handlingStrategy":"type-guard","validationCode":"static bool CanTransform(IList<ChatMessageContent> result, Type tOutput)\n    => tOutput.IsAssignableFrom(result.GetType())\n       || (result.Count == 1 && typeof(ChatMessageContent).IsAssignableFrom(tOutput))\n       || (result.Count == 1 && tOutput == typeof(string))\n       || (result.Count == 1 && IsValidJsonFor(result[0].Content ?? \"\", tOutput));","typeGuard":"// Narrow TOutput to shapes the default transform supports.\nbool outputIsSupported = typeof(TOutput) == typeof(string)\n    || typeof(ChatMessageContent).IsAssignableFrom(typeof(TOutput))\n    || typeof(IList<ChatMessageContent>).IsAssignableFrom(typeof(TOutput))\n    || typeof(TOutput).IsClass; // then ensure JSON payload","tryCatchPattern":"try { TOutput outVal = await DefaultTransforms.ToOutput<TOutput>(result, ct); }\ncatch (InvalidOperationException) { /* TOutput mismatch; switch TOutput or supply a custom transform */ }","preventionTips":["Align the orchestration's TOutput generic with the agent's actual output shape.","For structured types, ensure the agent emits valid JSON.","Provide a custom output transform when the default coercion is insufficient."],"tags":["orchestration","transforms","serialization","typing","dotnet"],"backgroundTag":null,"analyzedSha":"c028a0c7dc4f0814cdcbaba9d998f187a41197bf","analyzedAt":"2026-08-13T13:48:05.040Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}