错误处理

对于错误,OpenRoute AI 返回具有以下结构的 JSON 响应:

type ErrorResponse = {
  error: {
    code: number;
    message: string;
    metadata?: Record<string, unknown>;
  };
};

HTTP 响应将具有与 error.code 相同的状态代码,如果出现以下情况则形成请求错误:

  • 您的原始请求无效
  • 您的 API 密钥/账户信用额度不足

否则,返回的 HTTP 响应状态将为 S200_OK,LLM 生成输出时发生的任何错误都将在响应体中或作为 SSE 数据事件发出。

在 JavaScript 中打印错误的示例代码:

const request = await fetch('https://api.openroute.cn/...');
console.log(request.status); // 除非模型开始处理您的请求,否则将是错误代码
const response = await request.json();
console.error(response.error?.status); // 将是错误代码
console.error(response.error?.message);

错误代码

  • 400: 错误请求(无效或缺少参数,CORS)
  • 401: 无效凭据(OAuth 会话过期,禁用/无效的 API 密钥)
  • 402: 您的账户或 API 密钥信用额度不足。请添加更多信用额度并重试请求。
  • 403: 您选择的模型需要审核,您的输入被标记
  • 408: 您的请求超时
  • 429: 您正在被限流
  • 502: 您选择的模型已关闭或我们从中收到无效响应
  • 503: 没有可用的模型提供商满足您的路由要求

审核错误

如果您的输入被标记,error.metadata 将包含有关问题的信息。元数据的结构如下:

type ModerationErrorMetadata = {
  reasons: string[]; // 您的输入被标记的原因
  flagged_input: string; // 被标记的文本段,限制为 100 个字符。如果被标记的输入超过 100 个字符,将在中间截断并替换为 ...
  provider_name: string; // 请求审核的提供商名称
  model_slug: string;
};

提供商错误

如果模型提供商遇到错误,error.metadata 将包含有关问题的信息。元数据的结构如下:

type ProviderErrorMetadata = {
  provider_name: string; // 遇到错误的提供商名称
  raw: unknown; // 来自提供商的原始错误
};

当没有生成内容时

偶尔,模型可能不会生成任何内容。这通常发生在以下情况:

  • 模型正在从冷启动预热
  • 系统正在扩展以处理更多请求

预热时间通常从几秒到几分钟不等,具体取决于模型和提供商。

如果您遇到持续的无内容问题,请考虑实施简单的重试机制,或尝试使用具有更近期活动的不同提供商或模型。

此外,请注意,在某些情况下,即使没有生成内容,您仍可能被上游提供商收取提示处理费用。

流式错误格式

使用流式模式(stream: true)时,错误会根据发生时间的不同而采用不同的处理方式:

流前错误

在任何令牌发送之前发生的错误遵循上述标准错误格式,并具有适当的 HTTP 状态代码。

流中错误

流式传输开始后发生的错误将作为服务器发送事件(SSE)发送,具有包含错误详情和完成选择的统一结构:

type MidStreamError = {
  id: string;
  object: 'chat.completion.chunk';
  created: number;
  model: string;
  provider: string;
  error: {
    code: string | number;
    message: string;
  };
  choices: [{
    index: 0;
    delta: { content: '' };
    finish_reason: 'error';
    native_finish_reason?: string;
  }];
};

SSE 数据示例:

data: {"id":"cmpl-abc123","object":"chat.completion.chunk","created":1234567890,"model":"gpt-3.5-turbo","provider":"openai","error":{"code":"server_error","message":"Provider disconnected"},"choices":[{"index":0,"delta":{"content":""},"finish_reason":"error"}]}

关键特征:

  • 错误出现在顶层,与标准响应字段并列
  • 包含带有 finish_reason: "error" 的 choices 数组以正确终止流
  • HTTP 状态保持 200 OK,因为标头已经发送
  • 流在此事件后终止

OpenAI Responses API 错误事件

OpenAI Responses API(/api/alpha/responses)使用特定的事件类型来处理流式错误:

错误事件类型

  1. response.failed - 官方失败事件

    {
      "type": "response.failed",
      "response": {
        "id": "resp_abc123",
        "status": "failed",
        "error": {
          "code": "server_error",
          "message": "Internal server error"
        }
      }
    }
  2. response.error - 响应生成期间的错误

    {
      "type": "response.error",
      "error": {
        "code": "rate_limit_exceeded",
        "message": "Rate limit exceeded"
      }
    }
  3. error - 普通错误事件(未记录但由 OpenAI 发送)

    {
      "type": "error",
      "error": {
        "code": "invalid_api_key",
        "message": "Invalid API key provided"
      }
    }

错误代码转换

Responses API 将某些错误代码转换为具有特定完成原因的成功完成:

错误代码转换为完成原因
context_length_exceeded成功length
max_tokens_exceeded成功length
token_limit_exceeded成功length
string_too_long成功length

这允许优雅地处理基于限制的错误,而不将它们视为失败。

API 特定错误处理

不同的 OpenRoute AI API 端点以不同的方式处理错误:

OpenAI Chat Completions API (/api/v1/chat/completions)

  • 未发送令牌:返回独立的 ErrorResponse
  • 已发送部分令牌:在最终响应的 choices 数组中嵌入错误信息
  • 流式传输:错误作为带有顶层错误字段的 SSE 事件发送

OpenAI Responses API (/api/alpha/responses)

  • 错误转换:某些错误变为具有适当完成原因的成功响应
  • 流式事件:使用类型化事件(response.failed、response.error、error)
  • 优雅降级:通过回退行为处理提供商特定错误

错误响应类型定义

// 标准错误响应
interface ErrorResponse {
  error: {
    code: number;
    message: string;
    metadata?: Record<string, unknown>;
  };
}

// 带有完成数据的流中错误
interface StreamErrorChunk {
  error: {
    code: string | number;
    message: string;
  };
  choices: Array<{
    delta: { content: string };
    finish_reason: 'error';
    native_finish_reason: string;
  }>;
}

// Responses API 错误事件
interface ResponsesAPIErrorEvent {
  type: 'response.failed' | 'response.error' | 'error';
  error?: {
    code: string;
    message: string;
  };
  response?: {
    id: string;
    status: 'failed';
    error: {
      code: string;
      message: string;
    };
  };
}