Loading...
Loading...
Handle Venice API errors correctly. Covers the StandardError / DetailedError / ContentViolationError / X402InferencePaymentRequired body shapes, every meaningful status code (400, 401, 402, 403, 415, 422, 429, 500, 503, 504), the 402 PAYMENT-REQUIRED header used by x402 inference, 422 content-policy suggested_prompt retry pattern, 429 rate-limit headers, and an exponential-backoff retry strategy with idempotency.
npx skill4agent add veniceai/skills venice-errorsStandardError{ "error": "Unauthorized" }DetailedError400detailsformat()_errorsissues400StandardErrordetails{
"error": "Invalid request",
"details": {
"_errors": [],
"messages": { "_errors": ["Field is required"] }
},
"issues": [
{ "code": "invalid_type", "path": ["messages"], "message": "Field is required" }
]
}detailsissuesContentViolationErrorsuggested_prompt/audio/queue/audio/retrieve{ error: "Content policy violation" }suggested_prompt{
"error": "Content policy violation",
"suggested_prompt": "A cinematic instrumental track inspired by stormy weather and dramatic tension."
}suggested_promptprompt = suggested_promptX402InferencePaymentRequiredcode: "PAYMENT_REQUIRED"{
"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-REQUIREDpaymentRequiredx402Versionerrorresourceaccepts[]extensionsvenice-x402| Status | Body | Meaning | What to do |
|---|---|---|---|
| | Malformed input. Zod | Fix and re-send. Don't retry. |
| | Missing / invalid Bearer API key or SIWE. | Rotate credentials. Don't retry. |
| Bearer: | Out of DIEM/USD/wallet credit. | Bearer: top up at venice.ai. SIWE: run the x402 top-up flow. |
| | 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. |
| | Wrong | Fix headers. Don't retry. |
| | Content policy violation on generation paths; schema-ish validation on others. | On audio generation, optionally retry once with |
| | Rate limit cap tripped. Also returned by | Honor |
| | Unexpected failure. | Retry with exponential backoff + idempotency key where supported. |
| | Upstream model / service temporarily down. | Retry with backoff. Consider a fallback model. |
| | Upstream slow. Mostly on | Switch to |
429/crypto/rpc/{network}| Header | Meaning |
|---|---|
| Per-minute request cap for your tier (paid = 100, staff = 1000 on crypto RPC). |
| Requests remaining in the current 60-second window. |
| Unix timestamp in seconds when the window resets. |
LlmInferenceErrorRetry-After/api_keys/rate_limitsvenice-api-keysvenice-billing402| Header | Notes |
|---|---|
| Base64-encoded JSON of the x402 v2 |
400401403415Content-Type402402422suggested_prompt429X-RateLimit-Reset - now()500503504Idempotency-Key/crypto/rpc/{network}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')
}stream: truedata: {"error": {"type": "…", "message": "…"}}200X-Request-ID/crypto/rpc/*402/x402/top-upX-402-Paymentvenice-x402500/chat/completionsmax_tokens429/crypto/rpc/{network}customMessageDetailedError.details_errorsX-Rate-LimitX-RateLimitstreamdata: [DONE]