AI_JSONParseError during SSE streaming is not retried (falls to NamedError.Unknown) #9323

Open
opened 2026-02-16 18:12:11 -05:00 by yindo · 0 comments
Owner

Originally created by @konard on GitHub (Feb 14, 2026).

Originally assigned to: @thdxr on GitHub.

Description

When SSE streams from providers return malformed JSON (e.g., corrupted chunks from Kimi K2.5 via Kilo Gateway), the Vercel AI SDK throws AI_JSONParseError. In the current message-v2.ts:fromError() error classification chain, this error:

  1. Is NOT an APICallError (skips that branch)
  2. Is NOT a LoadAPIKeyError or DOMException (skips those branches)
  3. Falls through to case e instanceof Error: → becomes NamedError.Unknown

Since NamedError.Unknown is not recognized as retryable by retry.ts:retryable(), the session terminates immediately instead of retrying.

Evidence

This was observed in production:

{
  "name": "AI_JSONParseError",
  "text": "{\"id\":\"chatcmpl-jQugNdata:{\"id\":\"chatcmpl-iU6vkr3fItZ0Y4rTCmIyAnXO\",...}"
}

The error is classified as UnknownError and the session stops:

{
  "type": "error",
  "error": {
    "name": "UnknownError",
    "data": {
      "message": "AI_JSONParseError: JSON parsing failed: ..."
    }
  }
}

How Other CLI Agents Handle This

OpenAI Codex CLI: Skips unparseable SSE events and continues. CodexErr::Json is retryable with up to 5 stream retries.

Qwen Code: SDK's parseJsonLineSafe() silently skips failed lines.

Proposed Fix

In message-v2.ts:fromError(), add detection before the generic instanceof Error fallback:

case e instanceof Error: {
  const message = e.message || e.toString();
  const isStreamParseError =
    e.name === 'AI_JSONParseError' ||
    message.includes('AI_JSONParseError') ||
    message.includes('JSON parsing failed');
  if (isStreamParseError) {
    return new MessageV2.StreamParseError(
      { message, isRetryable: true, text: (e as any).text },
      { cause: e }
    ).toObject();
  }
  // ... existing socket/timeout checks
}

Related Issues

  • #7692: JSON Parse Error with Zhipu GLM-4.7: Stream chunks concatenated incorrectly
  • #8431: GLM 4.7 AI_JSONParseError
  • #10967: Error Writing Large Files with Kimi K2.5
  • vercel/ai#4099: streamText error handling
  • vercel/ai#12595: AI_JSONParseError should support retry

See: https://github.com/link-assistant/agent/issues/169

Originally created by @konard on GitHub (Feb 14, 2026). Originally assigned to: @thdxr on GitHub. ## Description When SSE streams from providers return malformed JSON (e.g., corrupted chunks from Kimi K2.5 via Kilo Gateway), the Vercel AI SDK throws `AI_JSONParseError`. In the current `message-v2.ts:fromError()` error classification chain, this error: 1. Is NOT an `APICallError` (skips that branch) 2. Is NOT a `LoadAPIKeyError` or `DOMException` (skips those branches) 3. Falls through to `case e instanceof Error:` → becomes `NamedError.Unknown` Since `NamedError.Unknown` is not recognized as retryable by `retry.ts:retryable()`, the session terminates immediately instead of retrying. ## Evidence This was observed in production: ```json { "name": "AI_JSONParseError", "text": "{\"id\":\"chatcmpl-jQugNdata:{\"id\":\"chatcmpl-iU6vkr3fItZ0Y4rTCmIyAnXO\",...}" } ``` The error is classified as `UnknownError` and the session stops: ```json { "type": "error", "error": { "name": "UnknownError", "data": { "message": "AI_JSONParseError: JSON parsing failed: ..." } } } ``` ## How Other CLI Agents Handle This **OpenAI Codex CLI**: Skips unparseable SSE events and continues. `CodexErr::Json` is retryable with up to 5 stream retries. **Qwen Code**: SDK's `parseJsonLineSafe()` silently skips failed lines. ## Proposed Fix In `message-v2.ts:fromError()`, add detection before the generic `instanceof Error` fallback: ```typescript case e instanceof Error: { const message = e.message || e.toString(); const isStreamParseError = e.name === 'AI_JSONParseError' || message.includes('AI_JSONParseError') || message.includes('JSON parsing failed'); if (isStreamParseError) { return new MessageV2.StreamParseError( { message, isRetryable: true, text: (e as any).text }, { cause: e } ).toObject(); } // ... existing socket/timeout checks } ``` ## Related Issues - #7692: JSON Parse Error with Zhipu GLM-4.7: Stream chunks concatenated incorrectly - #8431: GLM 4.7 AI_JSONParseError - #10967: Error Writing Large Files with Kimi K2.5 - vercel/ai#4099: streamText error handling - vercel/ai#12595: AI_JSONParseError should support retry See: https://github.com/link-assistant/agent/issues/169
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: anomalyco/opencode#9323