VoidnetVoid Docs
Reference

AI agents: read this documentation natively — index: https://docs.openvoidnet.com/llms.txt, full: https://docs.openvoidnet.com/llms-full.txt, this page: https://docs.openvoidnet.com/docs/reference/error-reference.md.

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 or JWT",
    "status": 401
  }
}

OAuth endpoints (POST /oauth/token, GET/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- 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- 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)
502publisher_errorLLM call ended with no usage.total_tokens chunkPublisher must send a final usage chunk (non-stream fails 502; relayed streams are error-metered) (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/messagesmodel and messages: [{role, content}] required
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