claude-api

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Claude API - Structured Outputs & Error Prevention Guide

Claude API - 结构化输出与错误预防指南

Package: @anthropic-ai/sdk@0.71.2 Breaking Changes: Oct 2025 - Claude 3.5/3.7 models retired, Nov 2025 - Structured outputs beta Last Updated: 2026-01-09

Package: @anthropic-ai/sdk@0.71.2 重大变更: 2025年10月 - Claude 3.5/3.7模型停用,2025年11月 - 结构化输出进入公测阶段 最后更新: 2026-01-09

What's New in v0.69.0+ (Nov 2025)

v0.69.0+(2025年11月)新特性

Major Features:
主要功能:

1. Structured Outputs (v0.69.0, Nov 14, 2025) - CRITICAL ⭐

1. 结构化输出(v0.69.0,2025年11月14日)- 核心功能 ⭐

Guaranteed JSON schema conformance - Claude's responses strictly follow your JSON schema with two modes.
⚠️ ACCURACY CAVEAT: Structured outputs guarantee format compliance, NOT accuracy. Models can still hallucinate—you get "perfectly formatted incorrect answers." Always validate semantic correctness (see below).
JSON Outputs (
output_format
)
- For data extraction and formatting:
typescript
import Anthropic from '@anthropic-ai/sdk';

const anthropic = new Anthropic({
  apiKey: process.env.ANTHROPIC_API_KEY,
});

const message = await anthropic.messages.create({
  model: 'claude-sonnet-4-5-20250929',
  max_tokens: 1024,
  messages: [{ role: 'user', content: 'Extract contact info: John Doe, john@example.com, 555-1234' }],
  betas: ['structured-outputs-2025-11-13'],
  output_format: {
    type: 'json_schema',
    json_schema: {
      name: 'Contact',
      strict: true,
      schema: {
        type: 'object',
        properties: {
          name: { type: 'string' },
          email: { type: 'string' },
          phone: { type: 'string' }
        },
        required: ['name', 'email', 'phone'],
        additionalProperties: false
      }
    }
  }
});

// Guaranteed valid JSON matching schema
const contact = JSON.parse(message.content[0].text);
console.log(contact.name); // "John Doe"
Strict Tool Use (
strict: true
)
- For validated function parameters:
typescript
const message = await anthropic.messages.create({
  model: 'claude-sonnet-4-5-20250929',
  max_tokens: 1024,
  messages: [{ role: 'user', content: 'Get weather for San Francisco' }],
  betas: ['structured-outputs-2025-11-13'],
  tools: [{
    name: 'get_weather',
    description: 'Get current weather',
    input_schema: {
      type: 'object',
      properties: {
        location: { type: 'string' },
        unit: { type: 'string', enum: ['celsius', 'fahrenheit'] }
      },
      required: ['location'],
      additionalProperties: false
    },
    strict: true  // ← Guarantees schema compliance
  }]
});
Requirements:
  • Beta header:
    structured-outputs-2025-11-13
    (via
    betas
    array)
  • Models: Claude Opus 4.5, Claude Sonnet 4.5, Claude Opus 4 (best models only)
  • SDK: v0.69.0+ required
Limitations:
  • ❌ No recursive schemas
  • ❌ No numerical constraints (
    minimum
    ,
    maximum
    )
  • ❌ Limited regex support (no backreferences/lookahead)
  • ❌ Incompatible with citations and message prefilling
  • ⚠️ Grammar compilation adds latency on first request (cached 24hrs)
Performance Characteristics:
  • First request: +200-500ms latency for grammar compilation
  • Subsequent requests: Normal latency (grammar cached for 24 hours)
  • Cache sharing: Only with IDENTICAL schemas (small changes = recompilation)
Pre-warming critical schemas:
typescript
// Pre-compile schemas during server startup
const warmupMessage = await anthropic.messages.create({
  model: 'claude-sonnet-4-5-20250929',
  max_tokens: 10,
  messages: [{ role: 'user', content: 'warmup' }],
  betas: ['structured-outputs-2025-11-13'],
  output_format: {
    type: 'json_schema',
    json_schema: YOUR_CRITICAL_SCHEMA
  }
});
// Later requests use cached grammar
Semantic Validation (CRITICAL):
typescript
const message = await anthropic.messages.create({
  model: 'claude-sonnet-4-5-20250929',
  messages: [{ role: 'user', content: 'Extract contact: John Doe' }],
  betas: ['structured-outputs-2025-11-13'],
  output_format: {
    type: 'json_schema',
    json_schema: contactSchema
  }
});

const contact = JSON.parse(message.content[0].text);

// ✅ Format is guaranteed valid
// ❌ Content may be hallucinated

// ALWAYS validate semantic correctness
if (!isValidEmail(contact.email)) {
  throw new Error('Hallucinated email detected');
}
if (contact.age < 0 || contact.age > 120) {
  throw new Error('Implausible age value');
}
When to Use:
  • Data extraction from unstructured text
  • API response formatting
  • Agentic workflows requiring validated tool inputs
  • Eliminating JSON parse errors
⚠️ SDK v0.71.1+ Deprecation: Direct
.parsed
property access is deprecated. Check SDK docs for updated API.
保证JSON Schema一致性 - Claude的响应将严格遵循你定义的JSON Schema,支持两种模式。
⚠️ 准确性说明: 结构化输出仅保证格式合规,不保证内容准确性。模型仍可能产生幻觉——你会得到"格式完全正确但内容错误的答案"。请始终验证语义正确性(见下文)。
JSON输出(
output_format
- 用于数据提取与格式化:
typescript
import Anthropic from '@anthropic-ai/sdk';

const anthropic = new Anthropic({
  apiKey: process.env.ANTHROPIC_API_KEY,
});

const message = await anthropic.messages.create({
  model: 'claude-sonnet-4-5-20250929',
  max_tokens: 1024,
  messages: [{ role: 'user', content: 'Extract contact info: John Doe, john@example.com, 555-1234' }],
  betas: ['structured-outputs-2025-11-13'],
  output_format: {
    type: 'json_schema',
    json_schema: {
      name: 'Contact',
      strict: true,
      schema: {
        type: 'object',
        properties: {
          name: { type: 'string' },
          email: { type: 'string' },
          phone: { type: 'string' }
        },
        required: ['name', 'email', 'phone'],
        additionalProperties: false
      }
    }
  }
});

// Guaranteed valid JSON matching schema
const contact = JSON.parse(message.content[0].text);
console.log(contact.name); // "John Doe"
严格工具调用(
strict: true
- 用于验证函数参数:
typescript
const message = await anthropic.messages.create({
  model: 'claude-sonnet-4-5-20250929',
  max_tokens: 1024,
  messages: [{ role: 'user', content: 'Get weather for San Francisco' }],
  betas: ['structured-outputs-2025-11-13'],
  tools: [{
    name: 'get_weather',
    description: 'Get current weather',
    input_schema: {
      type: 'object',
      properties: {
        location: { type: 'string' },
        unit: { type: 'string', enum: ['celsius', 'fahrenheit'] }
      },
      required: ['location'],
      additionalProperties: false
    },
    strict: true  // ← Guarantees schema compliance
  }]
});
要求:
  • 公测头:
    structured-outputs-2025-11-13
    (通过
    betas
    数组传入)
  • 模型: Claude Opus 4.5、Claude Sonnet 4.5、Claude Opus 4(仅限最优模型)
  • SDK: 需v0.69.0及以上版本
限制:
  • ❌ 不支持递归Schema
  • ❌ 不支持数值约束(
    minimum
    maximum
  • ❌ 正则表达式支持有限(不支持反向引用/正向预查)
  • ❌ 与引用标注和消息预填充不兼容
  • ⚠️ 首次请求时语法编译会增加延迟(缓存24小时)
性能特点:
  • 首次请求: 语法编译增加200-500ms延迟
  • 后续请求: 正常延迟(语法缓存24小时)
  • 缓存共享: 仅适用于完全相同的Schema(微小改动会触发重新编译)
预加载核心Schema:
typescript
// 在服务器启动时预编译Schema
const warmupMessage = await anthropic.messages.create({
  model: 'claude-sonnet-4-5-20250929',
  max_tokens: 10,
  messages: [{ role: 'user', content: 'warmup' }],
  betas: ['structured-outputs-2025-11-13'],
  output_format: {
    type: 'json_schema',
    json_schema: YOUR_CRITICAL_SCHEMA
  }
});
// 后续请求将使用缓存的语法
语义验证(核心步骤):
typescript
const message = await anthropic.messages.create({
  model: 'claude-sonnet-4-5-20250929',
  messages: [{ role: 'user', content: 'Extract contact: John Doe' }],
  betas: ['structured-outputs-2025-11-13'],
  output_format: {
    type: 'json_schema',
    json_schema: contactSchema
  }
});

const contact = JSON.parse(message.content[0].text);

// ✅ 格式保证有效
// ❌ 内容可能存在幻觉

// 始终验证语义正确性
if (!isValidEmail(contact.email)) {
  throw new Error('Hallucinated email detected');
}
if (contact.age < 0 || contact.age > 120) {
  throw new Error('Implausible age value');
}
适用场景:
  • 从非结构化文本中提取数据
  • API响应格式化
  • 需要验证工具输入的Agent工作流
  • 消除JSON解析错误
⚠️ SDK v0.71.1+弃用说明: 直接访问
.parsed
属性已被弃用,请查看SDK文档获取更新后的API。

2. Model Changes (Oct 2025) - BREAKING

2. 模型变更(2025年10月)- 重大变更

Retired (return errors):
  • ❌ Claude 3.5 Sonnet (all versions)
  • ❌ Claude 3.7 Sonnet - DEPRECATED (Oct 28, 2025)
Active Models (Jan 2026):
ModelIDContextBest ForCost (per MTok)
Claude Opus 4.5claude-opus-4-5-20251101200kFlagship - best reasoning, coding, agents$5/$25 (in/out)
Claude Sonnet 4.5claude-sonnet-4-5-20250929200kBalanced performance$3/$15 (in/out)
Claude Opus 4claude-opus-4-20250514200kHigh capability$15/$75
Claude Haiku 4.5claude-haiku-4-5-20250929200kNear-frontier, fast$1/$5
Note: Claude 3.x models (3.5 Sonnet, 3.7 Sonnet, etc.) are deprecated. Use Claude 4.x+ models.
已停用(调用将返回错误):
  • ❌ Claude 3.5 Sonnet(所有版本)
  • ❌ Claude 3.7 Sonnet - 已弃用(2025年10月28日)
当前可用模型(2026年1月):
模型ID上下文窗口最佳适用场景成本(每百万Token)
Claude Opus 4.5claude-opus-4-5-20251101200k旗舰模型 - 推理、编码、Agent能力最优$5/$25(输入/输出)
Claude Sonnet 4.5claude-sonnet-4-5-20250929200k性能均衡$3/$15(输入/输出)
Claude Opus 4claude-opus-4-20250514200k高能力模型$15/$75
Claude Haiku 4.5claude-haiku-4-5-20250929200k接近前沿水平,速度快$1/$5
注意: Claude 3.x系列模型(3.5 Sonnet、3.7 Sonnet等)已被弃用,请使用Claude 4.x及以上版本。

3. Context Management (Oct 28, 2025)

3. 上下文管理(2025年10月28日)

Clear Thinking Blocks - Automatic thinking block cleanup:
typescript
const message = await anthropic.messages.create({
  model: 'claude-sonnet-4-5-20250929',
  max_tokens: 4096,
  messages: [{ role: 'user', content: 'Solve complex problem' }],
  betas: ['clear_thinking_20251015']
});
// Thinking blocks automatically managed
清晰思维块 - 自动管理思维块:
typescript
const message = await anthropic.messages.create({
  model: 'claude-sonnet-4-5-20250929',
  max_tokens: 4096,
  messages: [{ role: 'user', content: 'Solve complex problem' }],
  betas: ['clear_thinking_20251015']
});
// Thinking blocks automatically managed

4. Agent Skills API (Oct 16, 2025)

4. Agent技能API(2025年10月16日)

Pre-built skills for Office files (PowerPoint, Excel, Word, PDF):
typescript
const message = await anthropic.messages.create({
  model: 'claude-sonnet-4-5-20250929',
  max_tokens: 1024,
  messages: [{ role: 'user', content: 'Analyze this spreadsheet' }],
  betas: ['skills-2025-10-02'],
  // Requires code execution tool enabled
});

针对Office文件(PowerPoint、Excel、Word、PDF)的预构建技能:
typescript
const message = await anthropic.messages.create({
  model: 'claude-sonnet-4-5-20250929',
  max_tokens: 1024,
  messages: [{ role: 'user', content: 'Analyze this spreadsheet' }],
  betas: ['skills-2025-10-02'],
  // Requires code execution tool enabled
});

Streaming Responses (SSE)

流式响应(SSE)

CRITICAL Error Pattern - Errors occur AFTER initial 200 response:
typescript
const stream = anthropic.messages.stream({
  model: 'claude-sonnet-4-5-20250929',
  max_tokens: 1024,
  messages: [{ role: 'user', content: 'Hello' }],
});

stream
  .on('error', (error) => {
    // Error can occur AFTER stream starts
    console.error('Stream error:', error);
    // Implement fallback or retry logic
  })
  .on('abort', (error) => {
    console.warn('Stream aborted:', error);
  });
Why this matters: Unlike regular HTTP errors, SSE errors happen mid-stream after 200 OK, requiring error event listeners

核心错误模式 - 错误可能在初始200响应后出现:
typescript
const stream = anthropic.messages.stream({
  model: 'claude-sonnet-4-5-20250929',
  max_tokens: 1024,
  messages: [{ role: 'user', content: 'Hello' }],
});

stream
  .on('error', (error) => {
    // Error can occur AFTER stream starts
    console.error('Stream error:', error);
    // Implement fallback or retry logic
  })
  .on('abort', (error) => {
    console.warn('Stream aborted:', error);
  });
重要性: 与常规HTTP错误不同,SSE错误会在200 OK响应后的流传输过程中发生,因此需要监听错误事件

Prompt Caching (⭐ 90% Cost Savings)

提示词缓存(⭐ 节省90%成本)

CRITICAL Rule -
cache_control
MUST be on LAST block:
typescript
const message = await anthropic.messages.create({
  model: 'claude-sonnet-4-5-20250929',
  max_tokens: 1024,
  system: [
    {
      type: 'text',
      text: 'System instructions...',
    },
    {
      type: 'text',
      text: LARGE_CODEBASE, // 50k tokens
      cache_control: { type: 'ephemeral' }, // ← MUST be on LAST block
    },
  ],
  messages: [{ role: 'user', content: 'Explain auth module' }],
});

// Monitor cache usage
console.log('Cache reads:', message.usage.cache_read_input_tokens);
console.log('Cache writes:', message.usage.cache_creation_input_tokens);
Minimum requirements:
  • Claude Sonnet 4.5: 1,024 tokens minimum
  • Claude Haiku 4.5: 2,048 tokens minimum
  • 5-minute TTL (refreshes on each use)
  • Cache shared only with IDENTICAL content
⚠️ AWS Bedrock Limitation: Prompt caching does NOT work for Claude 4 family on AWS Bedrock (works for Claude 3.7 Sonnet only). Use direct Anthropic API for Claude 4 caching support. (GitHub Issue #1347)

核心规则 -
cache_control
必须放在最后一个块上:
typescript
const message = await anthropic.messages.create({
  model: 'claude-sonnet-4-5-20250929',
  max_tokens: 1024,
  system: [
    {
      type: 'text',
      text: 'System instructions...',
    },
    {
      type: 'text',
      text: LARGE_CODEBASE, // 50k tokens
      cache_control: { type: 'ephemeral' }, // ← MUST be on LAST block
    },
  ],
  messages: [{ role: 'user', content: 'Explain auth module' }],
});

// Monitor cache usage
console.log('Cache reads:', message.usage.cache_read_input_tokens);
console.log('Cache writes:', message.usage.cache_creation_input_tokens);
最低要求:
  • Claude Sonnet 4.5: 最少1024个Token
  • Claude Haiku 4.5: 最少2048个Token
  • 5分钟TTL(每次使用时刷新)
  • 仅完全相同的内容可共享缓存
⚠️ AWS Bedrock限制: AWS Bedrock上的Claude 4系列模型不支持提示词缓存(仅Claude 3.7 Sonnet支持)。如需为Claude 4启用缓存支持,请使用Anthropic直接API。(GitHub Issue #1347)

Tool Use (Function Calling)

工具调用(函数调用)

CRITICAL Patterns:
Strict Tool Use (with structured outputs):
typescript
const message = await anthropic.messages.create({
  model: 'claude-sonnet-4-5-20250929',
  max_tokens: 1024,
  betas: ['structured-outputs-2025-11-13'],
  tools: [{
    name: 'get_weather',
    description: 'Get weather data',
    input_schema: {
      type: 'object',
      properties: {
        location: { type: 'string' },
        unit: { type: 'string', enum: ['celsius', 'fahrenheit'] }
      },
      required: ['location'],
      additionalProperties: false
    },
    strict: true  // ← Guarantees schema compliance
  }],
  messages: [{ role: 'user', content: 'Weather in NYC?' }]
});
Tool Result Pattern -
tool_use_id
MUST match:
typescript
const toolResults = [];
for (const block of response.content) {
  if (block.type === 'tool_use') {
    const result = await executeToolFunction(block.name, block.input);

    toolResults.push({
      type: 'tool_result',
      tool_use_id: block.id,  // ← MUST match tool_use block id
      content: JSON.stringify(result),
    });
  }
}

messages.push({
  role: 'user',
  content: toolResults,
});
Error Handling - Handle tool execution failures:
typescript
try {
  const result = await executeToolFunction(block.name, block.input);
  toolResults.push({
    type: 'tool_result',
    tool_use_id: block.id,
    content: JSON.stringify(result),
  });
} catch (error) {
  // Return error to Claude for handling
  toolResults.push({
    type: 'tool_result',
    tool_use_id: block.id,
    is_error: true,
    content: `Tool execution failed: ${error.message}`,
  });
}
Content Sanitization - Handle Unicode edge cases:
typescript
// U+2028 (LINE SEPARATOR) and U+2029 (PARAGRAPH SEPARATOR) cause JSON parse failures
function sanitizeToolResult(content: string): string {
  return content
    .replace(/\u2028/g, '\n') // LINE SEPARATOR → newline
    .replace(/\u2029/g, '\n'); // PARAGRAPH SEPARATOR → newline
}

const toolResult = {
  type: 'tool_result',
  tool_use_id: block.id,
  content: sanitizeToolResult(result) // Sanitize before sending
};

核心模式:
严格工具调用(结合结构化输出):
typescript
const message = await anthropic.messages.create({
  model: 'claude-sonnet-4-5-20250929',
  max_tokens: 1024,
  betas: ['structured-outputs-2025-11-13'],
  tools: [{
    name: 'get_weather',
    description: 'Get weather data',
    input_schema: {
      type: 'object',
      properties: {
        location: { type: 'string' },
        unit: { type: 'string', enum: ['celsius', 'fahrenheit'] }
      },
      required: ['location'],
      additionalProperties: false
    },
    strict: true  // ← Guarantees schema compliance
  }],
  messages: [{ role: 'user', content: 'Weather in NYC?' }]
});
工具结果模式 -
tool_use_id
必须匹配:
typescript
const toolResults = [];
for (const block of response.content) {
  if (block.type === 'tool_use') {
    const result = await executeToolFunction(block.name, block.input);

    toolResults.push({
      type: 'tool_result',
      tool_use_id: block.id,  // ← MUST match tool_use block id
      content: JSON.stringify(result),
    });
  }
}

messages.push({
  role: 'user',
  content: toolResults,
});
错误处理 - 处理工具执行失败:
typescript
try {
  const result = await executeToolFunction(block.name, block.input);
  toolResults.push({
    type: 'tool_result',
    tool_use_id: block.id,
    content: JSON.stringify(result),
  });
} catch (error) {
  // Return error to Claude for handling
  toolResults.push({
    type: 'tool_result',
    tool_use_id: block.id,
    is_error: true,
    content: `Tool execution failed: ${error.message}`,
  });
}
内容清理 - 处理Unicode边缘情况:
typescript
// U+2028 (LINE SEPARATOR) and U+2029 (PARAGRAPH SEPARATOR) cause JSON parse failures
function sanitizeToolResult(content: string): string {
  return content
    .replace(/\u2028/g, '\n') // LINE SEPARATOR → newline
    .replace(/\u2029/g, '\n'); // PARAGRAPH SEPARATOR → newline
}

const toolResult = {
  type: 'tool_result',
  tool_use_id: block.id,
  content: sanitizeToolResult(result) // Sanitize before sending
};

Vision (Image Understanding)

视觉能力(图像理解)

CRITICAL Rules:
  • Formats: JPEG, PNG, WebP, GIF (non-animated)
  • Max size: 5MB per image
  • Base64 overhead: ~33% size increase
  • Context impact: Images count toward token limit
  • Caching: Consider for repeated image analysis
Format validation - Check before encoding:
typescript
const validFormats = ['image/jpeg', 'image/png', 'image/webp', 'image/gif'];
if (!validFormats.includes(mimeType)) {
  throw new Error(`Unsupported format: ${mimeType}`);
}

核心规则:
  • 格式: JPEG、PNG、WebP、GIF(非动画)
  • 最大尺寸: 每张图片5MB
  • Base64开销: 尺寸增加约33%
  • 上下文影响: 图片会占用Token额度
  • 缓存: 重复分析图片时可考虑使用缓存
格式验证 - 编码前检查:
typescript
const validFormats = ['image/jpeg', 'image/png', 'image/webp', 'image/gif'];
if (!validFormats.includes(mimeType)) {
  throw new Error(`Unsupported format: ${mimeType}`);
}

Extended Thinking Mode

扩展思考模式

⚠️ Model Compatibility:
  • ❌ Claude 3.7 Sonnet - DEPRECATED (Oct 28, 2025)
  • ❌ Claude 3.5 Sonnet - RETIRED (not supported)
  • ✅ Claude Opus 4.5 - Extended thinking supported (flagship)
  • ✅ Claude Sonnet 4.5 - Extended thinking supported
  • ✅ Claude Opus 4 - Extended thinking supported
CRITICAL:
  • Thinking blocks are NOT cacheable
  • Requires higher
    max_tokens
    (thinking consumes tokens)
  • Check model before expecting thinking blocks

⚠️ 模型兼容性:
  • ❌ Claude 3.7 Sonnet - 已弃用(2025年10月28日)
  • ❌ Claude 3.5 Sonnet - 已停用(不支持)
  • ✅ Claude Opus 4.5 - 支持扩展思考(旗舰模型)
  • ✅ Claude Sonnet 4.5 - 支持扩展思考
  • ✅ Claude Opus 4 - 支持扩展思考
核心要点:
  • 思维块不可缓存
  • 需要更高的
    max_tokens
    (思考过程会消耗Token)
  • 期望获得思维块前请确认模型支持

Rate Limits

速率限制

CRITICAL Pattern - Respect
retry-after
header with exponential backoff:
typescript
async function makeRequestWithRetry(
  requestFn: () => Promise<any>,
  maxRetries = 3,
  baseDelay = 1000
): Promise<any> {
  for (let attempt = 0; attempt < maxRetries; attempt++) {
    try {
      return await requestFn();
    } catch (error) {
      if (error.status === 429) {
        // CRITICAL: Use retry-after header if present
        const retryAfter = error.response?.headers?.['retry-after'];
        const delay = retryAfter
          ? parseInt(retryAfter) * 1000
          : baseDelay * Math.pow(2, attempt);

        console.warn(`Rate limited. Retrying in ${delay}ms...`);
        await new Promise(resolve => setTimeout(resolve, delay));
      } else {
        throw error;
      }
    }
  }
  throw new Error('Max retries exceeded');
}
Rate limit headers:
  • anthropic-ratelimit-requests-limit
    - Total RPM allowed
  • anthropic-ratelimit-requests-remaining
    - Remaining requests
  • anthropic-ratelimit-requests-reset
    - Reset timestamp

核心模式 - 遵循
retry-after
头并使用指数退避:
typescript
async function makeRequestWithRetry(
  requestFn: () => Promise<any>,
  maxRetries = 3,
  baseDelay = 1000
): Promise<any> {
  for (let attempt = 0; attempt < maxRetries; attempt++) {
    try {
      return await requestFn();
    } catch (error) {
      if (error.status === 429) {
        // CRITICAL: Use retry-after header if present
        const retryAfter = error.response?.headers?.['retry-after'];
        const delay = retryAfter
          ? parseInt(retryAfter) * 1000
          : baseDelay * Math.pow(2, attempt);

        console.warn(`Rate limited. Retrying in ${delay}ms...`);
        await new Promise(resolve => setTimeout(resolve, delay));
      } else {
        throw error;
      }
    }
  }
  throw new Error('Max retries exceeded');
}
速率限制头:
  • anthropic-ratelimit-requests-limit
    - 允许的总请求数/分钟
  • anthropic-ratelimit-requests-remaining
    - 剩余请求数
  • anthropic-ratelimit-requests-reset
    - 重置时间戳

Error Handling

错误处理

Common Error Codes:
StatusError TypeCauseSolution
400invalid_request_errorBad parametersValidate request body
401authentication_errorInvalid API keyCheck env variable
403permission_errorNo access to featureCheck account tier
404not_found_errorInvalid endpointCheck API version
429rate_limit_errorToo many requestsImplement retry logic
500api_errorInternal errorRetry with backoff
529overloaded_errorSystem overloadedRetry later
CRITICAL:
  • Streaming errors occur AFTER initial 200 response
  • Always implement error event listeners for streams
  • Respect
    retry-after
    header on 429 errors
  • Have fallback strategies for critical operations

常见错误码:
状态码错误类型原因解决方案
400invalid_request_error参数错误验证请求体
401authentication_errorAPI密钥无效检查环境变量
403permission_error无功能访问权限检查账户层级
404not_found_error端点无效检查API版本
429rate_limit_error请求过多实现重试逻辑
500api_error内部错误使用退避策略重试
529overloaded_error系统过载稍后重试
核心要点:
  • 流式错误会在初始200响应后出现
  • 始终为流实现错误事件监听器
  • 429错误时请遵循
    retry-after
  • 为核心操作准备回退策略

Known Issues Prevention

已知问题预防

This skill prevents 16 documented issues:
本技能可预防16种已记录的问题:

Issue #1: Rate Limit 429 Errors Without Backoff

问题#1: 未使用退避策略导致的429速率限制错误

Error:
429 Too Many Requests: Number of request tokens has exceeded your per-minute rate limit
Source: https://docs.claude.com/en/api/errors Why It Happens: Exceeding RPM, TPM, or daily token limits Prevention: Implement exponential backoff with
retry-after
header respect
错误:
429 Too Many Requests: Number of request tokens has exceeded your per-minute rate limit
来源: https://docs.claude.com/en/api/errors 原因: 超出请求数/分钟、Token数/分钟或每日Token限制 预防: 实现指数退避策略并遵循
retry-after

Issue #2: Streaming SSE Parsing Errors

问题#2: SSE流式传输解析错误

Error: Incomplete chunks, malformed SSE events Source: Common SDK issue (GitHub #323) Why It Happens: Network interruptions, improper event parsing Prevention: Use SDK stream helpers, implement error event listeners
错误: 不完整的块、格式错误的SSE事件 来源: 常见SDK问题(GitHub #323) 原因: 网络中断、事件解析不当 预防: 使用SDK流助手,实现错误事件监听器

Issue #3: Prompt Caching Not Activating

问题#3: 提示词缓存未激活

Error: High costs despite cache_control blocks Source: https://platform.claude.com/docs/en/build-with-claude/prompt-caching Why It Happens:
cache_control
placed incorrectly (must be at END) Prevention: Always place
cache_control
on LAST block of cacheable content
错误: 已添加cache_control块但成本仍居高不下 来源: https://platform.claude.com/docs/en/build-with-claude/prompt-caching 原因:
cache_control
放置位置错误(必须在最后) 预防: 始终将
cache_control
放在可缓存内容的最后一个块上

Issue #4: Tool Use Response Format Errors

问题#4: 工具调用响应格式错误

Error:
invalid_request_error: tools[0].input_schema is invalid
Source: API validation errors Why It Happens: Invalid JSON Schema, missing required fields Prevention: Validate schemas with JSON Schema validator, test thoroughly
错误:
invalid_request_error: tools[0].input_schema is invalid
来源: API验证错误 原因: JSON Schema无效、缺少必填字段 预防: 使用JSON Schema验证器验证Schema,充分测试

Issue #5: Vision Image Format Issues

问题#5: 视觉能力图片格式问题

Error:
invalid_request_error: image source must be base64 or url
Source: API documentation Why It Happens: Incorrect encoding, unsupported formats Prevention: Validate format (JPEG/PNG/WebP/GIF), proper base64 encoding
错误:
invalid_request_error: image source must be base64 or url
来源: API文档 原因: 编码错误、格式不支持 预防: 验证格式(JPEG/PNG/WebP/GIF),正确进行Base64编码

Issue #6: Token Counting Mismatches for Billing

问题#6: 计费Token计数不匹配

Error: Unexpected high costs, context window exceeded Source: Token counting differences Why It Happens: Not accounting for special tokens, formatting Prevention: Use official token counter, monitor usage headers
错误: 成本超出预期、上下文窗口超限 来源: Token计数差异 原因: 未考虑特殊Token、格式影响 预防: 使用官方Token计数器,监控使用头

Issue #7: System Prompt Ordering Issues

问题#7: 系统提示词顺序问题

Error: System prompt ignored or overridden Source: API behavior Why It Happens: System prompt placed after messages array Prevention: ALWAYS place system prompt before messages
错误: 系统提示词被忽略或覆盖 来源: API行为特性 原因: 系统提示词放在messages数组之后 预防: 始终将系统提示词放在messages之前

Issue #8: Context Window Exceeded (200k)

问题#8: 上下文窗口超限(200k)

Error:
invalid_request_error: messages: too many tokens
Source: Model limits Why It Happens: Long conversations without pruning Prevention: Implement message history pruning, use caching
错误:
invalid_request_error: messages: too many tokens
来源: 模型限制 原因: 对话过长未进行修剪 预防: 实现消息历史修剪,使用缓存

Issue #9: Extended Thinking on Wrong Model

问题#9: 在错误的模型上使用扩展思考

Error: No thinking blocks in response Source: Model capabilities Why It Happens: Using retired/deprecated models (3.5/3.7 Sonnet) Prevention: Only use extended thinking with Claude Opus 4.5, Claude Sonnet 4.5, or Claude Opus 4
错误: 响应中无思维块 来源: 模型能力限制 原因: 使用已停用/弃用的模型(3.5/3.7 Sonnet) 预防: 仅在Claude Opus 4.5、Claude Sonnet 4.5或Claude Opus 4上使用扩展思考

Issue #10: API Key Exposure in Client Code

问题#10: 客户端代码中暴露API密钥

Error: CORS errors, security vulnerability Source: Security best practices Why It Happens: Making API calls from browser Prevention: Server-side only, use environment variables
错误: CORS错误、安全漏洞 来源: 安全最佳实践 原因: 在浏览器中直接调用API 预防: 仅在服务端调用,使用环境变量

Issue #11: Rate Limit Tier Confusion

问题#11: 速率限制层级混淆

Error: Lower limits than expected Source: Account tier system Why It Happens: Not understanding tier progression Prevention: Check Console for current tier, auto-scales with usage
错误: 限制低于预期 来源: 账户层级系统 原因: 不了解层级进阶规则 预防: 查看控制台当前层级,使用量会自动触发层级升级

Issue #12: Message Batches Beta Headers Missing

问题#12: 消息批量公测头缺失

Error:
invalid_request_error: unknown parameter: batches
Source: Beta API requirements Why It Happens: Missing
anthropic-beta
header Prevention: Include
anthropic-beta: message-batches-2024-09-24
header
错误:
invalid_request_error: unknown parameter: batches
来源: 公测API要求 原因: 缺少
anthropic-beta
预防: 添加
anthropic-beta: message-batches-2024-09-24

Issue #13: Stream Errors Not Catchable with .withResponse() (Fixed in v0.71.2)

问题#13: 使用.withResponse()时无法捕获流错误(v0.71.2已修复)

Error: Unhandled promise rejection when using
messages.stream().withResponse()
Source: GitHub Issue #856 Why It Happens: SDK internal error handling prevented user catch blocks from working (pre-v0.71.2) Prevention: Upgrade to v0.71.2+ or use event listeners instead
Fixed in v0.71.2+:
typescript
try {
  const stream = await anthropic.messages.stream({
    model: 'claude-sonnet-4-5-20250929',
    max_tokens: 1024,
    messages: [{ role: 'user', content: 'Hello' }]
  }).withResponse();
} catch (error) {
  // Now properly catchable in v0.71.2+
  console.error('Stream error:', error);
}
Workaround for pre-v0.71.2:
typescript
const stream = anthropic.messages.stream({
  model: 'claude-sonnet-4-5-20250929',
  max_tokens: 1024,
  messages: [{ role: 'user', content: 'Hello' }]
});

stream.on('error', (error) => {
  console.error('Stream error:', error);
});
错误: 使用
messages.stream().withResponse()
时出现未处理的Promise拒绝 来源: GitHub Issue #856 原因: SDK内部错误处理导致用户捕获块失效(v0.71.2之前版本) 预防: 升级到v0.71.2及以上版本,或使用事件监听器替代
v0.71.2及以上版本已修复:
typescript
try {
  const stream = await anthropic.messages.stream({
    model: 'claude-sonnet-4-5-20250929',
    max_tokens: 1024,
    messages: [{ role: 'user', content: 'Hello' }]
  }).withResponse();
} catch (error) {
  // Now properly catchable in v0.71.2+
  console.error('Stream error:', error);
}
v0.71.2之前版本的解决方法:
typescript
const stream = anthropic.messages.stream({
  model: 'claude-sonnet-4-5-20250929',
  max_tokens: 1024,
  messages: [{ role: 'user', content: 'Hello' }]
});

stream.on('error', (error) => {
  console.error('Stream error:', error);
});

Issue #14: MCP Tool Connections Cause 2-Minute Timeout

问题#14: MCP工具连接导致2分钟超时

Error:
Connection error
/
499 Client disconnected
after ~121 seconds Source: GitHub Issue #842 Why It Happens: MCP server connection management conflicts with long-running requests, even when MCP tools are not actively used Prevention: Use direct toolRunner instead of MCP for requests >2 minutes
Symptoms:
  • Request works fine without MCP
  • Fails at exactly ~121 seconds with MCP registered
  • Dashboard shows: "Client disconnected (code 499)"
  • Multiple users confirmed across streaming and non-streaming
Workaround:
typescript
// Don't use MCP for long requests
const message = await anthropic.beta.messages.toolRunner({
  model: 'claude-sonnet-4-5-20250929',
  max_tokens: 4096,
  messages: [{ role: 'user', content: 'Long task >2 min' }],
  tools: [customTools] // Direct tool definitions, not MCP
});
Note: This is a known limitation with no official fix. Consider architecture changes if long-running requests with tools are required.
错误:
Connection error
/
499 Client disconnected
(约121秒后) 来源: GitHub Issue #842 原因: 即使未主动使用MCP工具,MCP服务器连接管理也会与长时间运行的请求冲突 预防: 对于超过2分钟的请求,使用直接toolRunner而非MCP
症状:
  • 不使用MCP时请求正常
  • 使用MCP注册后,请求在约121秒时失败
  • 控制台显示: "Client disconnected (code 499)"
  • 流式和非流式请求均有多个用户确认此问题
解决方法:
typescript
// 长时间请求不要使用MCP
const message = await anthropic.beta.messages.toolRunner({
  model: 'claude-sonnet-4-5-20250929',
  max_tokens: 4096,
  messages: [{ role: 'user', content: 'Long task >2 min' }],
  tools: [customTools] // 直接定义工具,不使用MCP
});
注意: 这是已知限制,暂无官方修复。如果需要长时间运行的工具调用,请考虑架构调整。

Issue #15: Structured Outputs Hallucination Risk

问题#15: 结构化输出幻觉风险

Error: Valid JSON format but incorrect/hallucinated content Source: Structured Outputs Docs Why It Happens: Structured outputs guarantee format compliance, NOT accuracy Prevention: Always validate semantic correctness, not just format
typescript
const message = await anthropic.messages.create({
  model: 'claude-sonnet-4-5-20250929',
  messages: [{ role: 'user', content: 'Extract contact: John Doe' }],
  betas: ['structured-outputs-2025-11-13'],
  output_format: {
    type: 'json_schema',
    json_schema: contactSchema
  }
});

const contact = JSON.parse(message.content[0].text);

// ✅ Format is guaranteed valid
// ❌ Content may be hallucinated

// CRITICAL: Validate semantic correctness
if (!isValidEmail(contact.email)) {
  throw new Error('Hallucinated email detected');
}
if (contact.age < 0 || contact.age > 120) {
  throw new Error('Implausible age value');
}
错误: JSON格式有效但内容错误/存在幻觉 来源: 结构化输出文档 原因: 结构化输出仅保证格式合规,不保证内容准确性 预防: 始终验证语义正确性,而非仅验证格式
typescript
const message = await anthropic.messages.create({
  model: 'claude-sonnet-4-5-20250929',
  messages: [{ role: 'user', content: 'Extract contact: John Doe' }],
  betas: ['structured-outputs-2025-11-13'],
  output_format: {
    type: 'json_schema',
    json_schema: contactSchema
  }
});

const contact = JSON.parse(message.content[0].text);

// ✅ Format is guaranteed valid
// ❌ Content may be hallucinated

// CRITICAL: Validate semantic correctness
if (!isValidEmail(contact.email)) {
  throw new Error('Hallucinated email detected');
}
if (contact.age < 0 || contact.age > 120) {
  throw new Error('Implausible age value');
}

Issue #16: U+2028 Line Separator in Tool Results (Community-sourced)

问题#16: 工具结果中的U+2028行分隔符(社区发现)

Error: JSON parsing failures or silent errors when tool results contain U+2028 Source: GitHub Issue #882 Why It Happens: U+2028 is valid in JSON but not in JavaScript string literals Prevention: Sanitize tool results before passing to SDK
typescript
function sanitizeToolResult(content: string): string {
  return content
    .replace(/\u2028/g, '\n') // LINE SEPARATOR → newline
    .replace(/\u2029/g, '\n'); // PARAGRAPH SEPARATOR → newline
}

const toolResult = {
  type: 'tool_result',
  tool_use_id: block.id,
  content: sanitizeToolResult(result)
};

错误: 工具结果包含U+2028时出现JSON解析失败或静默错误 来源: GitHub Issue #882 原因: U+2028在JSON中有效,但在JavaScript字符串字面量中无效 预防: 传递给SDK前清理工具结果
typescript
function sanitizeToolResult(content: string): string {
  return content
    .replace(/\u2028/g, '\n') // LINE SEPARATOR → newline
    .replace(/\u2029/g, '\n'); // PARAGRAPH SEPARATOR → newline
}

const toolResult = {
  type: 'tool_result',
  tool_use_id: block.id,
  content: sanitizeToolResult(result)
};

Official Documentation

官方文档

Package Versions

包版本

Latest: @anthropic-ai/sdk@0.71.2
json
{
  "dependencies": {
    "@anthropic-ai/sdk": "^0.71.2"
  },
  "devDependencies": {
    "@types/node": "^20.0.0",
    "typescript": "^5.3.0",
    "zod": "^3.23.0"
  }
}

Token Efficiency:
  • Without skill: ~8,000 tokens (basic setup, streaming, caching, tools, vision, errors)
  • With skill: ~4,200 tokens (knowledge gaps + error prevention + critical patterns)
  • Savings: ~48% (~3,800 tokens)
Errors prevented: 16 documented issues with exact solutions Key value: Structured outputs (v0.69.0+), model deprecations (Oct 2025), prompt caching edge cases, streaming error patterns, rate limit retry logic, MCP timeout workarounds, hallucination validation

Last verified: 2026-01-20 | Skill version: 2.2.0 | Changes: Added 4 new issues from community research: streaming error handling (fixed in v0.71.2), MCP timeout workaround, structured outputs hallucination validation, U+2028 sanitization; expanded structured outputs section with performance characteristics and accuracy caveats; added AWS Bedrock caching limitation
最新版本: @anthropic-ai/sdk@0.71.2
json
{
  "dependencies": {
    "@anthropic-ai/sdk": "^0.71.2"
  },
  "devDependencies": {
    "@types/node": "^20.0.0",
    "typescript": "^5.3.0",
    "zod": "^3.23.0"
  }
}

Token效率:
  • 未使用本技能: ~8000个Token(基础设置、流式传输、缓存、工具、视觉、错误处理)
  • 使用本技能: ~4200个Token(知识缺口填补 + 错误预防 + 核心模式)
  • 节省: ~48%(约3800个Token)
预防的错误: 16种已记录的问题及精确解决方案 核心价值: 结构化输出(v0.69.0+)、模型弃用说明(2025年10月)、提示词缓存边缘情况、流式错误模式、速率限制重试逻辑、MCP超时解决方法、幻觉验证

最后验证: 2026-01-20 | 技能版本: 2.2.0 | 变更: 新增4个社区研究发现的问题:流式错误处理(v0.71.2已修复)、MCP超时解决方法、结构化输出幻觉验证、U+2028清理;扩展了结构化输出部分,增加性能特点和准确性说明;补充AWS Bedrock缓存限制