VoidnetVoid Docs
Reference

Error Reference

Complete, verified catalog of every error the Voidnet can return.

Every gateway error uses one JSON shape. The error field is an object with code, message, and status — not a string.

{
  "error": {
    "code": "api_key_invalid",
    "message": "Invalid token format. Expected: vnb-sk-xxx, vai-sk-xxx, or JWT",
    "status": 401
  }
}

OAuth endpoints (POST /oauth/token, POST /authorize, /.well-known/*) use a different shape: {"error": "<code>", "error_description": "<message>"}. These are noted below.


Authentication — 401

Returned when the Authorization header is missing, malformed, or the credential is unknown/expired.

CodeConditionFix
api_key_missingNo Authorization headerAdd Authorization: Bearer <credential>
api_key_invalidKey format is wrong, JWT header/signature invalid, or key not foundKey prefixes: vnb-sk-, vai-sk-, or a 3-segment JWT
api_key_expiredJWT access token expiredRequest a new token from POST /oauth/token
api_key_revokedKey was revoked in the ConsoleGenerate a new key
buyer_not_foundJWT is valid but the buyer no longer existsRequest a new token; contact support if it persists

The gateway auto-detects the credential type: a 3-segment (dot-separated) value is treated as a JWT; a vnb-sk-/vai-sk- prefix is treated as an API key.

WWW-Authenticate header is set on 401 (missing/invalid/expired key) and 403 insufficient_scope responses so OAuth-aware clients can bootstrap discovery.

OAuth — 400 / 401 / 405 / 500

Returned by POST /oauth/token, GET/POST /authorize, and the /.well-known/* metadata endpoints. These use the OAuth error shape, not the gateway envelope.

StatusCodeCondition
400invalid_requestBody unreadable or Content-Type is not application/x-www-form-urlencoded / application/json
400unsupported_grant_typegrant_type is not client_credentials, authorization_code, or refresh_token
400invalid_clientclient_id empty, bad prefix, or client_secret mismatch
400invalid_grantAuthorization code invalid/expired, PKCE mismatch, refresh token reused/rotated
400unsupported_response_typeresponse_type is not code
400invalid_requestMissing required params (client_id, redirect_uri, code_challenge, etc.)
401invalid_clientCredential lookup failed (key not found)
405unsupported_methodWrong HTTP method on a /.well-known/*, /oauth/token, or /authorize endpoint
500server_errorToken signing not configured or signing failed
404not_foundJWKS requested but signing not configured (on /.well-known/jwks.json)

Protocol — 400

Returned for MCP protocol version mismatches and header validation.

StatusCodeConditionFix
400UnsupportedProtocolVersionMCP-Protocol-Version header not 2026-07-28Use 2026-07-28 (MCP only)
400HeaderMismatchMCP-Protocol-Version header != _meta.protocolVersion in request bodyMake both match 2026-07-28 (MCP only)
400MissingRequiredClientCapabilityClient lacks a capability required by the methodAdd capability in _meta.clientCapabilities (MCP only)
400invalid_requestMissing required headers (MCP-Protocol-Version, Mcp-Method, Mcp-Name)Add all three headers (MCP only)
400invalid_requestLLM model or messages missing, or invalid JSONInclude {"model":"...","messages":[{"role":"user","content":"..."}]} (LLM only)
400invalid_requestLLM multimodal image_url/audio/video presentTEXT only — send content: string only (LLM)
502publisher_errorLLM stream ended with no usage.total_tokens chunkPublisher must send a final usage chunk (LLM streaming)

Billing — 402 / 403 / 429

Returned after authentication, when the purchase/subscription check or wallet deduct fails.

StatusCodeConditionFix
402insufficient_balanceWallet balance can't cover the call priceTop up at Console → Wallet ($5–$1000 via Stripe), then retry
403app_not_purchasedNo purchase or subscription recordPurchase (or "Get" a free tier) in the Marketplace
403subscription_inactiveSubscription exists but isn't activeCheck billing status in the Console
403subscription_expiredSubscription period endedRenew in the Console
403subscription_cancelledSubscription was cancelledContact support or repurchase
429meter_expiredBilling period expired, meter needs resetWait for meter reset

Metering — 400 / 501

Returned when the gateway can't record usage for the call. Rare — the call itself reached the publisher.

StatusCodeConditionFix
400invalid_recordMetering record failed validationRetry; contact support if it persists
400invalid_timestampMetering timestamp rejectedRetry; contact support if it persists
501protocol_not_supportedA2A metering attempted — A2A is not liveA2A is not available yet; use mcp or llm

Rate limiting — 429

Returned when a usage limit is exceeded. All limits use fixed-window counters.

StatusCodeConditionFix
429rate_limit_exceededRequest rate exceeded (per-minute or per-day)Wait for the window to reset, then retry with backoff
429meter_limit_exceededMonthly request quota exhaustedWait for the rolling 30-day reset, or upgrade tier

429 responses do not include a details payload. There are no X-RateLimit-* response headers. Track your usage in the Console.

Suspension / Scope — 403

StatusCodeCondition
403buyer_suspendedBuyer account suspended
403publisher_suspendedPublisher account suspended
403insufficient_scopeJWT scope doesn't permit the operation

Routing — 400 / 404

StatusCodeConditionFix
400invalid_pathURL doesn't match /v1-beta/{adapter}/{username}/{appname}Check the path
400invalid_adapter_typeDefensive only — unknown adapters never reach validation (routing returns 404 not_found first)Adapter segment is mcp or llm
400invalid_adapterDefensive only — route and adapter always match after routingUse mcp for tools, llm for chat
400invalid_requestLLM missing model/messages or multimodalmodel and messages: [{role, content:string}] required, TEXT only
400invalid_requestMissing fields or invalid JSON-RPC structureCheck the JSON-RPC body
404app_not_foundNo app registered for that username/appnameVerify both names
404publisher_not_foundPublisher username doesn't existCheck the username
404publisher_api_key_not_foundPublisher has no active API keyPublisher must regenerate their key
404purchase_not_foundPurchase record missing during usage queryConfirm the purchase

Publisher — 4xx / 5xx

Returned when the gateway proxies to the publisher and the publisher's server responds with an error.

StatusCodeCondition
4xxpublisher_client_errorPublisher returned a 400–499 (their error — check their docs)
5xxpublisher_server_errorPublisher returned a 500+ (their server error)
502publisher_errorPublisher transport/initialization failure
502app_offlineApp server unreachable — circuit opened after repeated failures
500publisher_not_payablePaid call blocked — publisher has no connected payout account
504gateway_timeoutPublisher didn't respond in time
501adapter_not_supportedRequested adapter isn't available (available: mcp, llm)
502publisher_error (LLM)Publisher returned invalid JSON or missing usage.total_tokens

Request — 400 / 404 / 405

StatusCodeCondition
400bad_requestUnparseable request
413body_too_largeRequest body exceeds the size limit
404not_foundNo route matches the URL
405method_not_allowedPUT/DELETE on a known route (GET routes to the pipeline; POST is the only write method)

Internal — 500

StatusCodeCondition
500internal_errorServer-side error — retry, then contact support
500database_errorDatabase query/write failed
500redis_errorRate-limit cache operation failed
500trace_errorFailed to start request tracing (non-critical)
500invalid_app_configApp configuration is invalid

On this page