microsoft/semantic-kernel · error · InvalidOperationException

Unable to transform output to {typeof(TOutput)}.

Error message

Unable to transform output to {typeof(TOutput)}.

What it means

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.

Source

Thrown at dotnet/src/Agents/Orchestration/Transforms/DefaultTransforms.cs:39

        IEnumerable<ChatMessageContent> TransformInput() =>
            input switch
            {
                IEnumerable<ChatMessageContent> messages => messages,
                ChatMessageContent message => [message],
                string text => [new ChatMessageContent(AuthorRole.User, text)],
                _ => [new ChatMessageContent(AuthorRole.User, JsonSerializer.Serialize(input))]
            };
    }

    public static ValueTask<TOutput> ToOutput<TOutput>(IList<ChatMessageContent> result, CancellationToken cancellationToken = default)
    {
        bool isSingleResult = result.Count == 1;

        TOutput output =
            GetDefaultOutput() ??
            GetObjectOutput() ??
            throw new InvalidOperationException($"Unable to transform output to {typeof(TOutput)}.");

        return new ValueTask<TOutput>(output);

        TOutput? GetObjectOutput()
        {
            if (!isSingleResult)
            {
                return default;
            }

            try
            {
                return JsonSerializer.Deserialize<TOutput>(result[0].Content ?? string.Empty);
            }
            catch (JsonException)
            {
                return default;
            }

View on GitHub (pinned to c028a0c7dc)

Solutions

  1. Make TOutput match what the agent actually produces (string or ChatMessageContent or IList<ChatMessageContent>).
  2. If you need a structured type, ensure the agent emits valid JSON for that type (prompt/instructions or a structured-output transform).
  3. Supply a custom orchestration output transform so the default ToOutput path is not used.

Example fix

// before: agent returns prose, but TOutput is a class
var orch = new MyOrchestration<string, SummaryPoco>(agent);

// after: align TOutput to actual output
var orch = new MyOrchestration<string, string>(agent);
// or instruct the agent to return JSON matching SummaryPoco and keep TOutput=SummaryPoco
Defensive patterns

Strategy: type-guard

Validate before calling

static bool CanTransform(IList<ChatMessageContent> result, Type tOutput)
    => tOutput.IsAssignableFrom(result.GetType())
       || (result.Count == 1 && typeof(ChatMessageContent).IsAssignableFrom(tOutput))
       || (result.Count == 1 && tOutput == typeof(string))
       || (result.Count == 1 && IsValidJsonFor(result[0].Content ?? "", tOutput));

Type guard

// Narrow TOutput to shapes the default transform supports.
bool outputIsSupported = typeof(TOutput) == typeof(string)
    || typeof(ChatMessageContent).IsAssignableFrom(typeof(TOutput))
    || typeof(IList<ChatMessageContent>).IsAssignableFrom(typeof(TOutput))
    || typeof(TOutput).IsClass; // then ensure JSON payload

Try / catch

try { TOutput outVal = await DefaultTransforms.ToOutput<TOutput>(result, ct); }
catch (InvalidOperationException) { /* TOutput mismatch; switch TOutput or supply a custom transform */ }

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of microsoft/semantic-kernel@c028a0c7dc (2026-08-13). Data as JSON: /api/errors/1fa7eb0fbdbb443d. Report an issue: GitHub.