venice-errors

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Venice errors & retries

Venice错误与重试

Every Venice endpoint returns one of four error shapes. Knowing which shape you got tells you how to react.
每个Venice端点都会返回四种错误结构之一。了解你遇到的错误结构可以指导你如何应对。

Error body shapes

错误体结构

1.
StandardError
— simple message

1.
StandardError
— 简单消息

The default shape for 4xx/5xx. Emitted when there's nothing structured to surface.
json
{ "error": "Unauthorized" }
这是4xx/5xx状态码的默认错误结构,当没有结构化信息需要展示时返回。
json
{ "error": "Unauthorized" }

2.
DetailedError
— Zod validation failure

2.
DetailedError
— Zod验证失败

Used for some
400
responses on malformed request bodies. When present,
details
is a Zod
format()
tree (
_errors
recursively keyed by field) alongside a flat
issues
array. Many
400
s are plain
StandardError
without
details
— always handle both.
json
{
  "error": "Invalid request",
  "details": {
    "_errors": [],
    "messages": { "_errors": ["Field is required"] }
  },
  "issues": [
    { "code": "invalid_type", "path": ["messages"], "message": "Field is required" }
  ]
}
Render
details
/
issues
to the user so they can fix the input; don't retry — the request shape is wrong.
用于请求体格式错误的部分
400
响应。当存在该错误时,
details
是Zod的
format()
树(按字段递归标记
_errors
),同时包含一个扁平化的
issues
数组。许多
400
错误是不带
details
的纯
StandardError
——请务必同时处理这两种情况。
json
{
  "error": "Invalid request",
  "details": {
    "_errors": [],
    "messages": { "_errors": ["Field is required"] }
  },
  "issues": [
    { "code": "invalid_type", "path": ["messages"], "message": "Field is required" }
  ]
}
details
/
issues
展示给用户,以便他们修正输入;请勿重试——请求格式本身存在问题。

3.
ContentViolationError
— 422 content policy

3.
ContentViolationError
— 422内容策略错误

Returned when a prompt trips content policy.
suggested_prompt
(a model-provided safe alternative) is currently emitted by the audio generation pipeline (
/audio/queue
,
/audio/retrieve
); image and video endpoints return
{ error: "Content policy violation" }
without
suggested_prompt
.
json
{
  "error": "Content policy violation",
  "suggested_prompt": "A cinematic instrumental track inspired by stormy weather and dramatic tension."
}
Pattern — when
suggested_prompt
is present, retry once with
prompt = suggested_prompt
if the user consents.
当提示触发内容策略限制时返回。
suggested_prompt
(模型提供的安全替代提示)目前仅由音频生成流水线(
/audio/queue
/audio/retrieve
)返回;图像和视频端点仅返回
{ error: "Content policy violation" }
,不带
suggested_prompt
json
{
  "error": "Content policy violation",
  "suggested_prompt": "A cinematic instrumental track inspired by stormy weather and dramatic tension."
}
处理模式 — 当存在
suggested_prompt
时,若用户同意,可使用
prompt = suggested_prompt
重试一次。

4.
X402InferencePaymentRequired
— 402 on x402 inference calls

4.
X402InferencePaymentRequired
— x402推理调用返回的402错误

Returned only when the caller authenticated with SIWE and has insufficient credit. Discriminated by
code: "PAYMENT_REQUIRED"
.
json
{
  "error": "Payment required",
  "code": "PAYMENT_REQUIRED",
  "message": "Insufficient x402 balance",
  "suggestedTopUpUsd": 10,
  "minimumTopUpUsd": 5,
  "supportedTokens": ["USDC"],
  "supportedChains": ["base"],
  "topUpInstructions": {
    "step1": "POST /api/v1/x402/top-up with no payment header to get payment requirements",
    "step2": "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": "<RECEIVER_WALLET_ADDRESS>",
    "tokenAddress": "<USDC_TOKEN_ADDRESS>",
    "tokenDecimals": 6,
    "network": "eip155:8453",
    "minimumAmountUsd": 5
  },
  "siwxChallenge": { ... SIWE template ... }
}
The
PAYMENT-REQUIRED
response header carries a base64-encoded x402 v2
paymentRequired
object (
x402Version
,
error
,
resource
,
accepts[]
, optional
extensions
) — it is not the same JSON as the body. Protocol-level clients parse the header; human-facing clients parse the richer body. See
venice-x402
.
仅当调用者通过SIWE认证但余额不足时返回。可通过
code: "PAYMENT_REQUIRED"
区分。
json
{
  "error": "Payment required",
  "code": "PAYMENT_REQUIRED",
  "message": "Insufficient x402 balance",
  "suggestedTopUpUsd": 10,
  "minimumTopUpUsd": 5,
  "supportedTokens": ["USDC"],
  "supportedChains": ["base"],
  "topUpInstructions": {
    "step1": "POST /api/v1/x402/top-up with no payment header to get payment requirements",
    "step2": "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": "<RECEIVER_WALLET_ADDRESS>",
    "tokenAddress": "<USDC_TOKEN_ADDRESS>",
    "tokenDecimals": 6,
    "network": "eip155:8453",
    "minimumAmountUsd": 5
  },
  "siwxChallenge": { ... SIWE template ... }
}
PAYMENT-REQUIRED
响应头携带base64编码的x402 v2
paymentRequired
对象(包含
x402Version
error
resource
accepts[]
、可选
extensions
)——它与响应体的JSON内容不同。协议级客户端解析该请求头;面向用户的客户端解析更丰富的响应体。详见
venice-x402

Status code map

状态码映射

StatusBodyMeaningWhat to do
400 Bad Request
DetailedError
Malformed input. Zod
details
identifies the field.
Fix and re-send. Don't retry.
401 Unauthorized
StandardError
Missing / invalid Bearer API key or SIWE.Rotate credentials. Don't retry.
402 Payment Required
Bearer:
StandardError
with the configured message (e.g.
{ "error": "Insufficient balance" }
— the handler's default path does not attach a
code
field). SIWE:
X402InferencePaymentRequired
+
PAYMENT-REQUIRED
header.
Out of DIEM/USD/wallet credit.Bearer: top up at venice.ai. SIWE: run the x402 top-up flow.
403 Forbidden
StandardError
Valid auth but not entitled. Typical: trial-limited endpoint, beta model, API-key consumption cap hit, SIWE signer ≠ path wallet.Don't retry. Investigate entitlements.
415 Unsupported Media Type
StandardError
Wrong
Content-Type
(e.g. JSON sent to a multipart endpoint, or vice versa).
Fix headers. Don't retry.
422 Unprocessable Entity
ContentViolationError
on image/audio/video generation; plain
{ error }
on other routes (e.g. ASR validation errors).
Content policy violation on generation paths; schema-ish validation on others.On audio generation, optionally retry once with
suggested_prompt
. On others, fix input.
429 Too Many Requests
StandardError
Rate limit cap tripped. Also returned by
/crypto/rpc/{network}
when credit-per-day or concurrency cap tripped.
Honor
X-RateLimit-*
headers, back off with jitter.
500 Internal Server Error
StandardError
Unexpected failure.Retry with exponential backoff + idempotency key where supported.
503 Service Unavailable
StandardError
Upstream model / service temporarily down.Retry with backoff. Consider a fallback model.
504 Gateway Timeout
StandardError
Upstream slow. Mostly on
/chat/completions
with huge contexts.
Switch to
stream: true
or shorter prompts.
状态码错误体含义处理方式
400 Bad Request
DetailedError
输入格式错误。Zod
details
会指明错误字段。
修正后重新发送。请勿重试。
401 Unauthorized
StandardError
缺少/无效的Bearer API密钥或SIWE认证。更换凭证。请勿重试。
402 Payment Required
Bearer认证:带配置消息的
StandardError
(例如
{ "error": "Insufficient balance" }
——默认处理逻辑不会附加
code
字段)。SIWE认证:
X402InferencePaymentRequired
+
PAYMENT-REQUIRED
请求头。
DIEM/USD/钱包余额不足。Bearer认证:前往venice.ai充值。SIWE认证:执行x402充值流程。
403 Forbidden
StandardError
认证有效但无权限。常见场景:试用版受限端点、测试模型、API密钥消耗上限、SIWE签名者与路径钱包不匹配。请勿重试。 检查权限配置。
415 Unsupported Media Type
StandardError
Content-Type
错误(例如向multipart端点发送JSON,或反之)。
修正请求头。请勿重试。
422 Unprocessable Entity
图像/音频/视频生成:
ContentViolationError
;其他路由:纯
{ error }
(例如ASR验证错误)。
生成路径触发内容策略限制;其他路径触发类 schema 验证错误。音频生成:可选择使用
suggested_prompt
重试一次。其他场景:修正输入。
429 Too Many Requests
StandardError
触发限流上限。当每日额度或并发上限触发时,
/crypto/rpc/{network}
也会返回该状态码。
遵循
X-RateLimit-*
请求头,添加抖动后退避。
500 Internal Server Error
StandardError
意外故障。在支持的情况下,使用指数退避+幂等键重试。
503 Service Unavailable
StandardError
上游模型/服务暂时不可用。退避后重试。考虑使用备用模型。
504 Gateway Timeout
StandardError
上游服务响应缓慢。主要出现在上下文超大的
/chat/completions
请求中。
切换为
stream: true
或缩短提示词。

Rate-limit headers (
429
)

限流请求头(
429

Emitted on
/crypto/rpc/{network}
:
HeaderMeaning
X-RateLimit-Limit
Per-minute request cap for your tier (paid = 100, staff = 1000 on crypto RPC).
X-RateLimit-Remaining
Requests remaining in the current 60-second window.
X-RateLimit-Reset
Unix timestamp in seconds when the window resets.
Additionally,
LlmInferenceError
model-overloaded conditions set a
Retry-After
header (seconds) on the 429 — honor it when present.
Inference endpoints (chat, image, audio, video) use a per-API-key tier defined via
/api_keys/rate_limits
. See
venice-api-keys
to pre-fetch your caps, and
venice-billing
for DIEM/USD usage.
/crypto/rpc/{network}
端点会返回以下请求头:
请求头含义
X-RateLimit-Limit
你的套餐每分钟请求上限(付费版=100,内部员工在加密RPC上=1000)。
X-RateLimit-Remaining
当前60秒窗口内剩余的请求次数。
X-RateLimit-Reset
窗口重置的Unix时间戳()。
此外,当模型过载触发
LlmInferenceError
时,429响应会附带
Retry-After
请求头(单位:秒)——请遵循该值。
推理端点(聊天、图像、音频、视频)使用通过
/api_keys/rate_limits
定义的每个API密钥的套餐限制。详见
venice-api-keys
预获取你的上限,以及
venice-billing
了解DIEM/USD使用情况。

Response headers on
402
(x402)

402
(x402)响应的请求头

HeaderNotes
PAYMENT-REQUIRED
Base64-encoded JSON of the x402 v2
paymentRequired
object (
x402Version
,
error
,
resource
,
accepts[]
, optional
extensions['sign-in-with-x']
). Protocol-level discovery — parse even if you don't parse the JSON body.
请求头说明
PAYMENT-REQUIRED
base64编码的x402 v2
paymentRequired
对象JSON(包含
x402Version
error
resource
accepts[]
、可选
extensions['sign-in-with-x']
)。协议级发现——即使不解析JSON体也需解析该请求头。

Retry strategy

重试策略

Never retry

绝不重试

  • 400
    — bad input. Fix the request.
  • 401
    — bad auth. Fix credentials.
  • 403
    — not entitled. Don't hammer.
  • 415
    — wrong
    Content-Type
    .
  • 400
    — 输入错误。修正请求。
  • 401
    — 认证错误。修正凭证。
  • 403
    — 无权限。请勿重复请求。
  • 415
    Content-Type
    错误。

Retry with modification

修改后重试

  • 402
    (x402) — run top-up then retry.
  • 402
    (Bearer) — surface to user; top up at venice.ai.
  • 422
    with
    suggested_prompt
    — one retry with the safer prompt.
  • 402
    (x402) — 完成充值后重试。
  • 402
    (Bearer) — 告知用户;前往venice.ai充值。
  • suggested_prompt
    422
    — 使用更安全的提示词重试一次。

Retry with backoff

退避后重试

  • 429
    — back off for at least
    X-RateLimit-Reset - now()
    . Add jitter.
  • 500
    /
    503
    /
    504
    — exponential backoff (e.g. 0.5s, 1s, 2s, 4s, 8s), capped at ~30s. 3–5 retries max.
  • Use
    Idempotency-Key
    (e.g. on
    /crypto/rpc/{network}
    ) so retries can't double-bill state-mutating calls.
  • 429
    — 至少等待
    X-RateLimit-Reset - now()
    时间。添加抖动。
  • 500
    /
    503
    /
    504
    — 指数退避(例如0.5s、1s、2s、4s、8s),最大延迟约30s。最多重试3–5次。
  • 使用
    Idempotency-Key
    (例如在
    /crypto/rpc/{network}
    上),确保重试不会导致状态变更类请求重复计费。

Reference retry loop

参考重试循环

ts
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 { status } = res

    if ([400, 401, 403, 415].includes(status)) {
      throw Object.assign(new Error(body.error ?? 'Venice error'), { status, body })
    }

    if (status === 402 && body.code === 'PAYMENT_REQUIRED') {
      await topUpX402(body.suggestedTopUpUsd)
      continue
    }

    if (status === 422) {
      throw Object.assign(new Error('Content policy'), { status, body })
    }

    if (status === 429) {
      const retryAfterSec = Number(res.headers.get('retry-after'))
      const resetSec = Number(res.headers.get('x-ratelimit-reset'))
      const waitMs = !Number.isNaN(retryAfterSec) && retryAfterSec > 0
        ? retryAfterSec * 1000
        : !Number.isNaN(resetSec) && resetSec > 0
          ? Math.max(resetSec * 1000 - Date.now(), delay)
          : delay
      await sleep(waitMs + Math.random() * 250)
      delay *= 2
      continue
    }

    if (status >= 500 && attempt < maxRetries) {
      await sleep(delay + Math.random() * 250)
      delay *= 2
      continue
    }

    throw Object.assign(new Error(body.error ?? 'Venice error'), { status, body })
  }
  throw new Error('Exceeded max retries')
}
ts
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 { status } = res

    if ([400, 401, 403, 415].includes(status)) {
      throw Object.assign(new Error(body.error ?? 'Venice error'), { status, body })
    }

    if (status === 402 && body.code === 'PAYMENT_REQUIRED') {
      await topUpX402(body.suggestedTopUpUsd)
      continue
    }

    if (status === 422) {
      throw Object.assign(new Error('Content policy'), { status, body })
    }

    if (status === 429) {
      const retryAfterSec = Number(res.headers.get('retry-after'))
      const resetSec = Number(res.headers.get('x-ratelimit-reset'))
      const waitMs = !Number.isNaN(retryAfterSec) && retryAfterSec > 0
        ? retryAfterSec * 1000
        : !Number.isNaN(resetSec) && resetSec > 0
          ? Math.max(resetSec * 1000 - Date.now(), delay)
          : delay
      await sleep(waitMs + Math.random() * 250)
      delay *= 2
      continue
    }

    if (status >= 500 && attempt < maxRetries) {
      await sleep(delay + Math.random() * 250)
      delay *= 2
      continue
    }

    throw Object.assign(new Error(body.error ?? 'Venice error'), { status, body })
  }
  throw new Error('Exceeded max retries')
}

Streaming errors

流式错误

Streaming responses (
stream: true
on chat, TTS, video-queue progress) deliver mid-stream errors as SSE events:
data: {"error": {"type": "…", "message": "…"}}
Treat them as terminal — the underlying connection is closed. The HTTP status is
200
because a successful stream can't be changed mid-flight.
流式响应(聊天、TTS、视频队列进度的
stream: true
)会通过SSE事件传递中途错误:
data: {"error": {"type": "…", "message": "…"}}
将此类错误视为终止信号——底层连接已关闭。HTTP状态码为
200
,因为成功启动的流无法中途修改状态。

Request-ID correlation

Request-ID关联

When present on a response, keep the
X-Request-ID
header. Include it in support tickets — Venice keys diagnostic logs by this ID.
/crypto/rpc/*
routes set it explicitly; many inference routes also include it, but don't assume it's universal — fall back to your own client-side correlation ID.
若响应中存在
X-Request-ID
请求头,请保留该值。在提交支持工单时包含它——Venice通过该ID关联诊断日志。
/crypto/rpc/*
路由会明确设置该请求头;许多推理路由也会包含,但不要假设它是通用的——若不存在,请回退使用客户端自己的关联ID。

Common gotchas

常见陷阱

  • A
    402
    from
    /x402/top-up
    with no
    X-402-Payment
    header is the expected discovery response, not an error. See
    venice-x402
    .
  • A
    500
    on
    /chat/completions
    with a huge file upload often means the upstream model chose to abort — reduce
    max_tokens
    / image size rather than blindly retrying.
  • 429
    on
    /crypto/rpc/{network}
    may mean the 24-hour credit cap tripped, not the per-minute one. Check
    customMessage
    .
  • DetailedError.details
    is a Zod
    _errors
    tree, not a flat map. Walk it recursively.
  • Some endpoints (image generation) echo
    X-Rate-Limit
    variants — treat any header whose name starts with
    X-RateLimit
    as advisory.
  • Don't treat an empty
    stream
    chunk as an error — send-keepalives look like
    data: [DONE]
    or empty lines.
  • 不带
    X-402-Payment
    请求头调用
    /x402/top-up
    返回的
    402
    预期的发现响应,而非错误。详见
    venice-x402
  • 上传大文件时
    /chat/completions
    返回
    500
    通常意味着上游模型主动终止——请减小
    max_tokens
    /图像大小,而非盲目重试。
  • /crypto/rpc/{network}
    返回的
    429
    可能意味着触发了24小时额度上限,而非每分钟上限。请检查
    customMessage
  • DetailedError.details
    是Zod的
    _errors
    树,而非扁平化映射。请递归遍历它。
  • 部分端点(图像生成)会返回
    X-Rate-Limit
    变体——将任何名称以
    X-RateLimit
    开头的请求头视为参考值。
  • 请勿将空的
    stream
    块视为错误——保活信号看起来像
    data: [DONE]
    或空行。