{"record":{"id":"c524c0fb53d691ca","repo":"microsoft/autogen","slug":"failed-to-deserialize-response","errorCode":null,"errorMessage":"Failed to deserialize response","messagePattern":"Failed to deserialize response","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"dotnet/src/AutoGen.Anthropic/AnthropicClient.cs","lineNumber":96,"sourceCode":"                    currentEvent.Data = line.Substring(\"data:\".Length).Trim();\n                }\n            }\n            else // an empty line indicates the end of an event\n            {\n                if (currentEvent.EventType == \"content_block_start\" && !string.IsNullOrEmpty(currentEvent.Data))\n                {\n                    var dataBlock = JsonSerializer.Deserialize<DataBlock>(currentEvent.Data!);\n                    if (dataBlock != null && dataBlock.ContentBlock?.Type == \"tool_use\")\n                    {\n                        currentEvent.ContentBlock = dataBlock.ContentBlock;\n                    }\n                }\n\n                if (currentEvent.EventType is \"message_start\" or \"content_block_delta\" or \"message_delta\" && currentEvent.Data != null)\n                {\n                    var res = await JsonSerializer.DeserializeAsync<ChatCompletionResponse>(\n                        new MemoryStream(Encoding.UTF8.GetBytes(currentEvent.Data)),\n                        cancellationToken: cancellationToken) ?? throw new Exception(\"Failed to deserialize response\");\n                    if (res.Delta?.Type == \"input_json_delta\" && !string.IsNullOrEmpty(res.Delta.PartialJson) &&\n                        currentEvent.ContentBlock != null)\n                    {\n                        currentEvent.ContentBlock.AppendDeltaParameters(res.Delta.PartialJson!);\n                    }\n                    else if (res.Delta is { StopReason: \"tool_use\" } && currentEvent.ContentBlock != null)\n                    {\n                        if (res.Content == null)\n                        {\n                            res.Content = [currentEvent.ContentBlock.CreateToolUseContent()];\n                        }\n                        else\n                        {\n                            res.Content.Add(currentEvent.ContentBlock.CreateToolUseContent());\n                        }\n\n                        currentEvent = new SseEvent();\n                    }","sourceCodeStart":78,"sourceCodeEnd":114,"githubUrl":"https://github.com/microsoft/autogen/blob/027ecf0a379bcc1d09956d46d12d44a3ad9cee14/dotnet/src/AutoGen.Anthropic/AnthropicClient.cs#L78-L114","documentation":"In AnthropicClient's SSE streaming path, this exception means JsonSerializer.DeserializeAsync returned null for the data payload of a message_start / content_block_delta / message_delta event. Because the data is known non-null at that point, a null result indicates the JSON did not bind to ChatCompletionResponse — almost always an API/model response-shape change (new fields, renamed fields, or a variant schema) that the client's DTOs can't deserialize into a non-null instance.","triggerScenarios":"Calling AnthropicClient.CreateChatCompletionAsync (or the streaming API used by AnthropicClientAgent) with streaming enabled while Anthropic has introduced a response-shape change (e.g. new block types, thinking/output-format changes); mismatch between the beta header 'prompt-caching-2024-07-31' behavior and the account/model's actual SSE format.","commonSituations":"Anthropic API update after the AutoGen.Anthropic package was built; model-version-specific streaming payloads (e.g. tool-use heavy turns); proxies that rewrite/truncate the SSE stream; using an old package against new claude models.","solutions":["Update AutoGen.Anthropic to the latest release — DTO fixes for new Anthropic response shapes land there.","If it persists, capture the raw SSE data (log currentEvent.Data) and compare against the current Anthropic streaming docs; a field rename in ChatCompletionResponse is the usual culprit.","Test with streaming disabled (non-streaming path, error 96's code path) to isolate whether only the streaming schema broke.","Check for corporate proxies that buffer/mangle SSE and feed invalid JSON fragments to the deserializer."],"exampleFix":"// before\nvar res = await JsonSerializer.DeserializeAsync<ChatCompletionResponse>(...)\n    ?? throw new Exception(\"Failed to deserialize response\");\n\n// after (surface the payload that failed to bind for diagnosis)\nvar res = await JsonSerializer.DeserializeAsync<ChatCompletionResponse>(...)\n    ?? throw new JsonException($\"Failed to deserialize SSE event '{currentEvent.EventType}' data: {currentEvent.Data}\");","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"retryPolicy: Polly RetryStrategyOptions<ChatCompletionResponse>\n{\n    MaxRetryAttempts = 2,\n    ShouldHandle = new PredicateBuilder<ChatCompletionResponse>()\n        .Handle<Exception>(ex => ex.Message == \"Failed to deserialize response\"),\n    Delay = TimeSpan.FromSeconds(2),\n    BackoffType = DelayBackoffType.Exponential\n}\n// transient schema glitches and truncated SSE frames often succeed on retry","preventionTips":["Pin to a tested AutoGen.Anthropic version and a stable Anthropic model id; upgrade both together.","Log raw SSE event data (EventType + Data) at debug level in production so deserialization failures are diagnosable from logs.","Run a nightly smoke test against the live streaming endpoint to catch API drift before your users do."],"tags":["anthropic","sse","streaming","json-deserialization","api-drift","autogen"],"backgroundTag":null,"analyzedSha":"027ecf0a379bcc1d09956d46d12d44a3ad9cee14","analyzedAt":"2026-08-15T03:38:00.719Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}