mcpField
V
venice-errors

venice-errors

github.com/veniceai开发160137 次安装5 天前更新
代码仓库

关于 venice-errors

venice-errors 是 Venice API 的错误与重试参考,面向需要处理 API 响应的开发者。它按状态码梳理错误结构、限流信息及对应处理方式,涵盖 x402 认证与支付错误。

主要功能

  1. 01归纳常见错误响应结构
  2. 02按状态码说明错误含义
  3. 03介绍限流响应头与错误预算
  4. 04说明 x402 支付和签名错误
  5. 05提供重试或修正建议

适用场景

  1. 01为 API 客户端编写错误处理
  2. 02区分可重试与不可重试错误
  3. 03排查 x402 认证或余额问题
  4. 04处理限流与模型过载响应

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/veniceai/skills --skill venice-errors

安装后在 Claude Code 中输入/venice-errors确认已加载。

详细介绍

Venice 错误与重试

Venice 的大多数错误都采用 { "error": "<message>" } 格式,但有几种情况会附带结构化信息。了解错误的具体格式,就能知道该如何处理。

错误响应体格式

1. StandardError — 简单消息

4xx/5xx 错误的默认格式。

{ "error": "Authentication failed" }
2. DetailedError — 架构验证失败(400)

请求不符合 Venice 自身的架构时,details 是一个嵌套树(按字段递归列出 _errors),而 issues 是扁平的问题列表。某些图像、视频和上游错误则会将 details 作为普通字符串返回,因此遍历前请先检查其类型。

{
  "error": "Invalid request parameters",
  "details": {
    "_errors": [],
    "type": { "_errors": ["Invalid enum value. Expected 'asr' | 'decision' | … , received 'bogus'", "Invalid enum value. Expected 'all' | 'code', received 'bogus'"] }
  },
  "issues": [
    { "code": "invalid_union", "unionErrors": [ … ], "path": ["type"], "message": "Invalid input" }
  ]
}

(这是对 GET /models?type=bogus 的实时响应。)

许多 400 错误采用普通的 StandardError 格式,请同时处理这两种情况。显示 details / issues;不要重试。

3. OpenAI 风格的上下文溢出(400,聊天)
{
  "error": {
    "message": "Your request exceeds the model's maximum context. Please reduce your prompt or completion length.",
    "type": "invalid_request_error",
    "param": "messages",
    "code": "context_length_exceeded"
  }
}

请注意,此处的 error 是一个对象,因此 OpenAI SDK 可以识别它。message 是 Venice 能提取时使用的提供方措辞,否则就是上方的文本;请根据 code 而不是 message 进行判断。缩短提示词或降低 max_completion_tokens。

4. 上游提供方拒绝请求(400)

请求通过 Venice 的架构验证,但模型提供方拒绝请求时,Venice 会返回提供方的消息,并在会跟踪请求 ID 的路由上附带 request_id(例如聊天路由;/decisions 不会附带):

{ "error": "<provider's validation message>", "request_id": "…" }

FastAPI 风格的验证错误(例如 POST /decisions 背后的 TypeSafe 提供方返回的 422)会以 400 返回,其中最多包含五条 field.path: message,并以 ; 连接。如果 Venice 无法提取消息,你会收到 "Invalid request parameters. For assistance, please reach out to [email protected]";若存在请求 ID,后面还会附加 " and reference request ID: <id>"。这些错误会计入聊天 / responses 中宽松的不支持功能额度(参见错误额度)。修正输入;联系支持时请提供 request_id。

5. ContentViolationError — 内容政策错误(422)
{
  "error": "Your prompt violates the content policy of Venice.ai or the model provider",
  "suggested_prompt": "A cinematic instrumental track inspired by stormy weather and dramatic tension."
}

聊天、responses、图像编辑和多重编辑以及音频生成都会返回此错误。/image/generate 不使用此错误(被拦截的图像会以 200 状态返回,并附带 x-venice-is-content-violation: true),而视频内容政策拒绝会在 /video/retrieve 返回,而不是在排队时返回。suggested_prompt 仅由 /audio/queue 和 /audio/retrieve 返回;如果存在,且用户同意,可使用它重试一次。其他 422 错误包括 "Your input was blocked by content moderation." 和媒体验证失败(图像过大、宽高比错误、音频 / 视频时长超出范围、ASR 无法处理该音频)。

6. ProviderContentPolicyError — /video/retrieve 的 422
{
  "error": {
    "message": "The selected model provider rejected this request due to its content policies. Credits have been refunded. Try using <model> instead.",
    "type": "provider_content_policy",
    "credits_refunded": true,
    "recommended_model": "<model id>"
  }
}

检查 credits_refunded;也可以使用 recommended_model 重新排队。

7. PayloadTooLargeError — 413
{ "code": "PAYLOAD_TOO_LARGE", "error": "File exceeds the maximum allowed size of 25 MB." }
8. x402 402 响应体

402 有两种形式。两种形式都会设置 PAYMENT-REQUIRED 请求头。无凭据形式会在所有需要凭据的路由上返回,包括仅限 Bearer 的路由(/api_keys*、/billing/*、/characters*),这些路由不适用其中的支付选项。

完全没有凭据 - x402 v2 发现(不是 401):

{
  "x402Version": 2,
  "error": "Authentication required",
  "resource": { "url": "https://api.venice.ai/api/v1/chat/completions", "description": "Venice API", "mimeType": "application/json" },
  "accepts": [ { "scheme": "exact", "network": "eip155:8453", "…": "…" }, { "scheme": "exact", "network": "solana", "…": "…" } ],
  "extensions": { "sign-in-with-x": { "info": { "domain": "api.venice.ai", "statement": "Sign in to Venice AI", "…": "…" }, "supportedChains": [ … ] } },
  "authOptions": {
    "apiKey": { "header": "Authorization: Bearer YOUR_API_KEY", "getKey": "https://venice.ai/settings/api", "docs": "…" },
    "x402Wallet": { "header": "SIGN-IN-WITH-X", "legacyHeader": "X-Sign-In-With-X", "topUp": "POST /api/v1/x402/top-up", "docs": "…" }
  }
}

已登录钱包余额低于最低限额 $0.10 - 根据 code: "PAYMENT_REQUIRED" 进行区分:

{
  "error": "Payment required",
  "code": "PAYMENT_REQUIRED",
  "reason": "insufficient_balance",
  "currentBalanceUsd": 0.01,
  "minimumBalanceUsd": 0.1,
  "description": "Venice API",
  "suggestedTopUpUsd": 10,
  "minimumTopUpUsd": 5,
  "supportedTokens": ["USDC"],
  "supportedChains": ["base", "solana"],
  "topUpInstructions": {
    "step1": "POST /api/v1/x402/top-up with no payment header to get payment requirements",
    "step2": "Choose a payment option from accepts and sign a USDC transfer authorization using the x402 SDK (createPaymentHeader)",
    "step3": "POST /api/v1/x402/top-up with the signed X-402-Payment header",
    "receiverWallet": "0x…",
    "tokenAddress": "0x…",
    "tokenDecimals": 6,
    "network": "eip155:8453",
    "minimumAmountUsd": 5
  },
  "siwxChallenge": { "info": { … }, "supportedChains": [ … ] }
}

topUpInstructions 仅说明 Base 通道;如需通过 Solana 支付,请从 POST /x402/top-up 读取 accepts[](并发送 PAYMENT-SIGNATURE,这是规范请求头 - X-402-Payment / X-PAYMENT 仍然可用)。PAYMENT-REQUIRED 请求头是 base64 编码的 x402 paymentRequired 对象(x402Version、error、resource、accepts[]、extensions),而不是响应体。请参阅 venice-x402。

API 密钥的 402 响应是纯文本:{ "error": "Insufficient USD or Diem balance to complete request. Visit https://venice.ai/settings/api to add credits." },或者针对每个密钥的支出限额变体(“API key DIEM spend limit exceeded…” / “API key USD spend limit exceeded…”)。当钱包的额度高于 $0.10 下限,但不足以支付此请求的报价时(例如 /video/queue、/audio/queue),也可能收到同样的纯文本“Insufficient USD or Diem balance…”响应体 - 充值后重试。

9. x402 登录失败(401)

在推理路由上,错误的 SIGN-IN-WITH-X 会返回 { "error": "<message>", "code": "X402_SIGN_IN_…" }(例如 X402_SIGN_IN_EXPIRED、X402_SIGN_IN_NONCE_REUSED)。/x402/balance 和 /x402/transactions 会返回通用的 { "error": "Invalid Sign-in-with-x signature" }。所有代码请参阅 venice-auth。

状态码对照表

状态码典型响应正文含义处理方法
400DetailedError、StandardError、上下文溢出对象,或上游 { error, request_id }输入格式错误、缺少 model 或其值不是字符串(纯文本错误为 "model is required" / "model must be a string")、此模型不支持的选项、提供商拒绝请求、JSON 无效("Invalid JSON request"),或 POST 请求的 Content-Type 既不是 JSON 也不是 multipart("'Content-Type' must be 'application/json'")。如果向推理路由而非 /x402/top-up 发送 x402 支付标头,也会返回 PAYMENT_HEADER_NOT_ACCEPTED。修正后重新发送。不要重试。
401StandardError 或 { error, code }API 密钥未知、已过期或已撤销("Authentication failed")、在仅限管理员的路由上使用了非 ADMIN 密钥("Admin API key required")、SIWX 错误,或出现 "This model is only available to Pro users"(使用 Pro 专属模型的 API 密钥账户没有付费套餐)。修正凭据或套餐。不要重试。
402参见形态 8未提供凭据(发现阶段)、钱包余额过低,或 API 密钥账户 / 密钥的支出限额已用尽。x402:充值后重试。API 密钥:添加额度或提高密钥的限额。
403StandardError有权限但被阻止:模型在你所在的国家/地区被屏蔽(regionRestrictions)、密钥的 modelPrivacy 禁止使用该模型、API 访问已禁用、SIWX 钱包 ≠ 路径中的钱包。不要重试。
404StandardError未知模型("Specified model not found: …",有时会附带建议或 "has been deprecated. Please use …" 提示)、未知角色、媒体已过期。修正 ID。
409{ error: { code: "needs_consent", message }, consent_flow, face_media_roles, consent, docs_url }(视频)或 { error, message, details }(x402)/video/queue 需要用户同意(仅未列出的模型 ID 会要求;已列出的模型不会要求),或 x402 充值已处理或仍在结算中(error 中包含代码,例如 "PAYMENT_IN_PROGRESS"——请稍后重试)。参见 venice-video / venice-x402。
410StandardError端点已停用(GET /billing/usage、POST /video/transcriptions)。消息中会注明替代端点。迁移。绝不要重试。
413PayloadTooLargeErrorJSON 正文超过 35 MB("Request body exceeds the maximum allowed size."),或 multipart 文件超过 25 MB。缩小上传内容。
415StandardError少见情况:/image/multi-edit 请求正文为空,或请求正文使用了服务端无法解码的 Content-Encoding / 字符集("Request encoding is not supported")。任何路由上的 Content-Type 错误都会返回 400。修正标头。
422ContentViolationError、ProviderContentPolicyError 或 StandardError内容策略违规,或媒体无法处理(尺寸、时长、音频无法读取)。修改提示词或媒体。若提供了 suggested_prompt,可重试一次。
429StandardError 或 { error, code }请求 / 令牌速率限制、错误预算耗尽、模型过载、x402 并发限制(X402_CONCURRENCY_LIMIT,每个钱包最多 5 个并发请求),或特定路由的限流器(加密货币 RPC、/x402/*、/tee/*、已停用的端点)。参见下方的速率限制说明。
500StandardError意外故障。采用退避策略后重试。
502StandardError上游故障(TTS、ASR、TEE、视频获取)。采用退避策略后重试。
503StandardError模型离线或已达容量上限。采用退避策略;考虑使用备用模型。
504StandardError请求耗时过长。大多发生于非流式聊天。使用 stream: true 或缩小请求。

速率限制及其标头

有三组互相独立的标头——它们共享前缀,但单位不同,因此请按完整名称准确识别:

标头发出方重置单位
x-ratelimit-limit-requests、x-ratelimit-remaining-requests、x-ratelimit-reset-requests(以及 -tokens 变体)推理路由上的模型速率限制(按账户、模型分别计算,限制每分钟/每天的请求数和每分钟的令牌数)Unix 毫秒
x-ratelimit-remaining、x-ratelimit-resets错误预算,出现在大多数需要凭证的路由响应中(不包括无凭证时的 402)Unix 毫秒
X-RateLimit-Limit、X-RateLimit-Remaining、X-RateLimit-Reset/crypto/rpc/{network},仅在触发其每分钟上限时返回的 429 响应中出现Unix 秒

模型限制触发的 429 会返回 "Rate limit exceeded"。请使用 GET /api_keys/rate_limits 预先查询额度(仅限 Bearer 密钥)。历史触发记录可通过 GET /api_keys/rate_limits/log 查看,此接口需要 ADMIN 密钥——INFERENCE 密钥会收到 401 "Admin API key required"(venice-api-keys)。

各路由的限制器返回的 429 不带这些标头:/x402/top-up(每个 IP 每分钟 10 次)、/x402/balance(每个钱包每分钟 30 次)和 /x402/transactions(每个钱包每分钟 20 次)会返回 "Rate limit exceeded. Please try again later.";/tee/*(每个 IP 每分钟 10 次)会返回 "Rate limit exceeded.";已停用的端点允许每个 IP 每分钟 60 次。

上游过载:返回带有 Retry-After 的 429(单位为秒,默认 30),以及类似 "The model is currently overloaded. Please try again later." 的消息。请遵循 Retry-After。

错误预算

失败请求受到的速率限制比成功请求更严格:

预算阈值计数范围记录为
失败请求每 30 s 50 次任意 4xx,429 除外(5xx 不计数)FAILED_REQUESTS
不支持功能的请求每 30 s 200 次,仅限 /chat/completions 和 /responses请求模型执行其不具备的功能,或服务提供方拒绝其他方面有效的请求UNSUPPORTED_FEATURE_REQUESTS

计数桶按 API 密钥(x402 按 IP)、model 和 OpenAI 的 user 字符串划分;分块上传无法及时提取 model/user,因此会共用该密钥(或 IP)的计数桶。计数桶耗尽后,其中的每个请求在重置前都会收到 429,并附带:

Too many failed attempts (> 50) resulting in a non-success status code. Please wait 30 seconds and try again. See https://docs.venice.ai/api-reference/rate-limiting for more information.

不支持功能的计数桶会使用相同措辞,但阈值为 > 200。因此,盲目重试 400/401/402 的客户端会导致自身被锁定。遇到不可重试的错误时请停止重试。(无凭证时的 402、Content-Type 和无效 JSON 导致的 400,以及 35 MB JSON 请求体导致的 413,都会在检查预算前被拒绝,因此不计入预算。)

重试策略

切勿重试

400、401、403、404、410、413、415——请修正请求、凭证或端点。

修改后重试
  • 402 且 code: "PAYMENT_REQUIRED"——在用户消费上限内通过 /x402/top-up 充值(参见 venice-x402),然后重试。
  • 带有 x402Version 的 402(无凭证)——添加 Authorization: Bearer …,或在支持钱包的路由上使用 SIGN-IN-WITH-X。仅限 Bearer 的路由(/api_keys*、/billing/*、/characters*)会以 401 拒绝 SIWX;请在这些路由上发送 Bearer 密钥。
  • 使用钱包身份验证进行的任何重试都需要新签名的 SIGN-IN-WITH-X 标头——每个 nonce 只能接受一次,因此重新发送原标头会导致 X402_SIGN_IN_NONCE_REUSED。
  • API 密钥收到 402 时——向用户显示该错误。
  • 422 且带有 suggested_prompt——使用更安全的提示词重试一次。
使用退避策略重试
  • 429 - 如果存在 Retry-After,则等待指定时间;否则等待到相关重置标头指示的时间,并加入随机抖动。
  • 500 / 502 / 503 / 504 - 使用指数退避(0.5 s、1 s、2 s、4 s、8 s),最长约 30 s,最多重试 3-5 次。
  • 异步队列(/video/queue、/audio/queue、/audio/voice-changer/queue)可能会在任务完成前计费(API 密钥调用会在入队时预扣费用)。如果队列响应丢失,请轮询 retrieve,而不是重新入队。仅 /crypto/rpc/{network} 支持 Idempotency-Key。
重试循环参考
const sleep = (ms: number) => new Promise(r => setTimeout(r, ms))

function waitMs(res: Response, fallback: number): number {
  const retryAfter = Number(res.headers.get('retry-after'))
  if (retryAfter > 0) return retryAfter * 1000
  const msReset = Number(res.headers.get('x-ratelimit-reset-requests') ?? res.headers.get('x-ratelimit-resets'))
  if (msReset > 0) return Math.max(msReset - Date.now(), fallback)
  const secReset = Number(res.headers.get('x-ratelimit-reset')) // crypto RPC
  if (secReset > 0) return Math.max(secReset * 1000 - Date.now(), fallback)
  return fallback
}

// fn must build a fresh SIGN-IN-WITH-X header on every call; nonces are single-use.
async function callVenice<T>(fn: () => Promise<Response>): Promise<T> {
  const maxRetries = 5
  let delay = 500
  for (let attempt = 0; attempt <= maxRetries; attempt++) {
    const res = await fn()
    if (res.ok) return res.json() as Promise<T>

    const body = await res.clone().json().catch(() => ({}))
    const message = typeof body.error === 'string' ? body.error : body.error?.message ?? 'Venice error'
    const fail = () => Object.assign(new Error(message), { status: res.status, body })

    if ([400, 401, 403, 404, 410, 413, 415, 422].includes(res.status)) throw fail()

    if (res.status === 402) {
      // topUpAllowed must enforce the user's cap and check GET /x402/balance first.
      if (body.code === 'PAYMENT_REQUIRED' && attempt === 0 && (await topUpAllowed())) {
        await topUpX402(Math.min(body.suggestedTopUpUsd, USER_TOP_UP_CAP_USD))
        continue
      }
      throw fail()
    }

    if ((res.status === 429 || res.status >= 500) && attempt < maxRetries) {
      await sleep((res.status === 429 ? waitMs(res, delay) : delay) + Math.random() * 250)
      delay = Math.min(delay * 2, 30_000)
      continue
    }

    throw fail()
  }
  throw new Error('Exceeded max retries')
}

流式错误

如果 /chat/completions 流在发送标头后失败,HTTP 状态仍为 200,错误会以内嵌方式返回,随后是终止符:

data: {"error":{"message":"…","type":"server_error","code":"model_overloaded","param":null,"retry_after":30}}
data: [DONE]

过载错误使用 type: "server_error"、code: "model_overloaded",并可能携带 retry_after(秒);其他上游故障使用 type: "api_error",其 code 为 "upstream_error" 或特定代码(例如 e2ee_attestation_stale)。应将此事件视为终止事件。

请求 ID 关联

聊天请求的上游拒绝响应正文包含 request_id,而 /crypto/rpc/{network} 会在代理响应中设置 X-Request-ID 标头。提交支持工单时,请附上其中任一项(以及响应标头中的 x-venice-version)。其他路由不保证提供请求 ID,因此也请保留自己的客户端关联 ID。

常见注意事项

  • /x402/top-up 返回的、不带支付标头的 402 响应是预期的发现响应。
  • 推理路由返回 402(而非 401)通常意味着你完全没有发送身份验证标头。
  • 不带后缀的 x-ratelimit-remaining 表示错误预算,而非请求配额。
  • 429 可能由多种限制器触发(模型限制、错误预算、过载、x402 并发数、单路由上限)——请先阅读消息和标头,再决定等待多久。
  • 架构验证失败导致 400 时,DetailedError.details 是嵌套的 _errors 树,而非扁平映射;某些图像、视频或上游故障会将其作为普通字符串发送。遍历前请检查其类型。
  • 在 SSE 流中,data: [DONE] 表示流已结束(错误块之后也一样),而非保活信号。

评论

支持 Markdown