Skip to content

bug(streaming): JSON.parse crashes on invalid escape sequences in model output #996

@bilal-azam

Description

@bilal-azam

Bug Report

Description

When Claude outputs a string containing certain escape sequences that are valid in some contexts but not strict JSON (e.g., \d, \p, \s as regex literals inside a JSON string), the streaming parser crashes with an unhandled SyntaxError. This surfaces as an unhandled rejection that crashes the entire application.

Reproduction

import Anthropic from '@anthropic-ai/sdk';

const client = new Anthropic();

// Ask Claude to produce output containing regex-like content
const stream = await client.messages.stream({
  model: 'claude-sonnet-4-6',
  max_tokens: 500,
  messages: [{
    role: 'user',
    content: 'Return a JSON object with a "pattern" field containing the regex \\d+\\.\\d+ as a string value. Return ONLY the JSON.'
  }],
});

// This may crash: SyntaxError: Invalid escape sequence
const message = await stream.finalMessage();

Expected Behavior

The SDK should gracefully handle malformed JSON from the model, either by:

  1. Attempting lenient JSON parsing (JSON5 / repair strategies)
  2. Returning the raw string with a warning
  3. Emitting a recoverable error event instead of throwing

Actual Behavior

SyntaxError: Invalid or unexpected token
at JSON.parse ()
at MessageStream.parse (src/lib/MessageStream.ts:XXX)
...

The error is unhandled and crashes the Node.js process.

Proposed Fix

Wrap all JSON.parse calls in the streaming pipeline with a recovery strategy:

function safeParseJSON<T>(text: string): T | null {
  try {
    return JSON.parse(text) as T;
  } catch {
    // Attempt to repair common model output issues
    const repaired = repairInvalidEscapes(text);
    try {
      return JSON.parse(repaired) as T;
    } catch {
      return null; // Emit warning, don't crash
    }
  }
}

Environment

  • @anthropic-ai/sdk version: latest
  • Node.js version: 20.x
  • Trigger: Models asked to produce JSON containing regex patterns, Windows paths, LaTeX

I'm happy to submit a PR. 🙏

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions