-
-
Notifications
You must be signed in to change notification settings - Fork 69.5k
[Bug] Azure Foundry Anthropic: SSE stream events concatenated without \n\n delimiter — raw JSON parse error surfaced to all user channels #32179
Description
Description
When using the azure-foundry-anthropic provider (Azure AI Foundry Anthropic endpoint at *.services.ai.azure.com/anthropic) with api: "anthropic-messages", the SSE stream occasionally delivers chunks where two SSE events are concatenated without a proper \n\n delimiter between them. The @anthropic-ai/sdk LineDecoder fails to split these correctly, causing JSON.parse() to receive a malformed string combining two events.
The error is then surfaced verbatim as a "run error" message to the user in Discord channels and webchat — on every session type (direct, group, sub-agents, cron).
Steps to Reproduce
- Configure an
azure-foundry-anthropicprovider pointing tohttps://<hub>.services.ai.azure.com/anthropic - Use
api: "anthropic-messages"with a Claude Sonnet 4.x model - Run multiple concurrent agent sessions (crons + sub-agents + direct chat)
- Within 2 hours: observe SSE parse errors in gateway logs
Observed Behavior
Gateway logs (journalctl --user -u openclaw-gateway):
Could not parse message into JSON: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" Director, Regulatory Affairs | 1"}} event: content_block_delta
Could not parse message into JSON: {"type":"content_block_delta","index":1,"delta":{"type":"input_json_delta","partial_json":"ary_foevent: content_block_delta
Could not parse message into JSON: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":","} }
Could not parse message into JSON: {"type":"message_delta","delta":{"stop_reason":"tool_use","stop_sequence":null},"usage":{"input_tokens":3,event: content_block_delta
Patterns observed:
- Two events concatenated with spaces instead of
\n\n:}} event: content_block_delta - Mid-JSON truncation with next event header:
"partial_json":"ary_foevent: content_block_delta - Trailing whitespace garbage before closing brace:
"text":","} }
Frequency: ~17 errors per 2 hours under moderate concurrency (10 concurrent agents, 8 sub-agents max).
Impact: [agent/embedded] embedded run agent end: isError=true — the error is delivered as a "run error" message to Discord channels and webchat on every occurrence. Users see raw JSON parse errors in all channels.
Expected Behavior
- The SSE parser should tolerate Azure Foundry's non-standard chunk delimiters (defensive splitting on
event:keyword boundaries in addition to\n\n) - OR: auto-retry the request (1-2 times) on transient SSE parse failures before surfacing to user
- At minimum: the error should NOT be delivered to end-user channels — it should be logged and silently retried
Environment
- OpenClaw: 2026.3.1
- @anthropic-ai/sdk: 0.73.0
- Model:
azure-foundry-anthropic/claude-sonnet-4-6(custom provider,api: "anthropic-messages") - Provider endpoint:
https://<hub>.services.ai.azure.com/anthropic - Node.js: v22.22.0
- OS: Linux 6.17.0 (Azure VM, x64)
Root Cause Analysis
The @anthropic-ai/sdk/internal/decoders/line.ts LineDecoder correctly splits on \n and \r\n. However, Azure Foundry Anthropic's endpoint appears to occasionally send HTTP response chunks where the SSE event boundary (\n\n) is missing or replaced with whitespace. Two consecutive data: lines arrive merged in a single chunk without a newline separator, causing the LineDecoder to return one oversized "line" that contains both events — which then fails JSON.parse().
This is distinct from issue #14321 (C0 control characters). The issue here is event boundary encoding specific to Azure Foundry's streaming implementation.
Suggested Fix
In the SSE stream handler (@anthropic-ai/sdk/core/streaming.js → called from OpenClaw's streamSimpleAnthropic):
// Defensive split: if sse.data contains concatenated events, split on "event:" boundaries
function safeSplitSSEData(data: string): string {
// If data contains "event:" mid-string (Azure Foundry concatenation artifact),
// truncate to first valid JSON object
const eventIdx = data.search(/\s+event:/);
if (eventIdx > 0) {
return data.substring(0, eventIdx).trim();
}
return data;
}Or alternatively: wrap the JSON.parse(sse.data) in a try/catch that silently retries the streaming request rather than surfacing the error to users.
Related Issues
- [Bug] Raw JSON parse error surfaced to user when Anthropic SSE stream contains control characters #14321 — similar class: SSE parse errors surfaced to user (C0 control characters variant)
- PR fix: sanitize error messages to prevent internal details and PII from leaking to end users #20251 — partially addresses error formatting (not merged)