Error reference
This page is the canonical envelope reference for the Shroud API: the HTTP status table, the JSON shape every error follows, the request_id and Retry-After semantics callers should observe, and the per-transport notes for HTTP, MCP, JSON-RPC, and the Cocoon WebSocket. For the auto-generated, exhaustive list of structured codes see Error codes. For caller-side action mapping (when to retry, when to surface, when to alert) see Production guide — Error handling map.
Error envelope
Every error response from the gateway carries the same JSON shape on the HTTP path:
Field | Type | Notes |
|---|---|---|
| string | Human-readable message. Stable enough for log lines, never parse. |
| string | Stable |
| object (optional) | Structured payload specific to the code. Omitted when there is nothing to add. |
Content-Type: application/json is set on every error response, including the 401 and 429 paths that some legacy docs described as "plain text" — the gateway has emitted JSON envelopes since 2025 and no path falls back to plain text. The full code list and per-code HTTP status mapping is in Error codes.
HTTP status table
Status codes used by middleware before reaching the handler:
HTTP | Code | Cause |
|---|---|---|
400 |
| Caller-side validation failure. |
401 |
| Missing or malformed |
403 |
| Authenticated, but the key lacks the capability for this tool. |
404 |
| Resource or tool name does not exist on this deployment. |
409 |
| Idempotency-Key in flight on a concurrent request, or other state conflict. |
410 |
| Two-step confirmation token expired. |
422 |
| Idempotency-Key reused with a different request body. |
429 |
| Per-key or per-IP request rate exceeded. |
429 |
| Per-key or workspace Credit Unit budget exhausted. |
500 |
| Server-side or upstream tool failure. |
503 |
| Upstream dependency briefly unavailable. |
Authentication errors (401)
SHROUD_UNAUTHORIZED is returned with HTTP 401 Unauthorized and the canonical envelope. Common triggers:
Trigger | Message |
|---|---|
No |
|
Header without a |
|
Key whose format does not match |
|
Key environment does not match the deployment environment |
|
Key not found, revoked, or expired |
|
The Bearer prefix is required exactly. Token <key>, lowercase bearer, and the bare key with no prefix are all rejected. See Authentication for the supported header forms and key lifecycle.
Rate limit errors (429)
There are two distinct 429 Too Many Requests paths. Both use the canonical envelope; they differ in error_code, in Retry-After, and in whether details is populated.
Per-key / per-IP RPS (SHROUD_RATE_LIMITED)
Retry-After: 1. Returned when the per-key token-bucket trips for authenticated callers, or when an anonymous (no-key) request exceeds 5 RPS for its source IP. See Production guide — Rate limits and CU budgets for the per-plan caps and the anonymous bucket rules.
CU limit (SHROUD_CU_LIMIT_EXCEEDED)
Retry-After: 60. The same code is used for per-key rolling-window limits and for workspace-wide plan limits; the scope is signalled by the presence of details.window:
Scope |
| Other fields |
|---|---|---|
Per-key 24-hour limit |
|
|
Per-key 30-day limit |
|
|
Workspace plan + purchased balance exhausted | absent |
|
used_cu_milli and limit_cu_milli are reported in milli-CU; divide by 1,000 for CU and by 1,000,000,000 for USD. See Billing for the unit definitions.
Retry-After semantics
The gateway sets Retry-After as a hint, not a guarantee. The recommended caller pattern is to honour it as the floor and apply your own jittered exponential backoff on top:
Retry-After values currently emitted by the gateway:
Code | Header |
|---|---|
|
|
|
|
|
|
When the OpenAI-compatible chat-completions path returns 503 because the upstream Cocoon worker is unavailable, the response body uses OpenAI shape rather than the SHROUD envelope. See OpenAI-compatible API for that special case.
Request correlation
Every request carries a session correlation ID written to the gateway logs. Pass X-Request-Id on the request and the gateway will echo it on the response so client logs and server logs can be joined post-hoc. Always log the request id alongside any non-2xx status — when filing a bug or support ticket the id is the fastest way for the team to find the matching server-side trace.
The MCP transport additionally returns a session id in the Mcp-Session-Id response header on the initialize call. Subsequent requests on the same agent session should echo this header back; see MCP API for the full session lifecycle.
Transport-specific envelopes
The shape above is what HTTP-level callers see. Tool-layer errors emerge through three transports, and each wraps the SHROUD code slightly differently.
HTTP path (OpenAI-compatible / Cocoon SSE shim)
The OpenAI-compatible chat-completions endpoint surfaces upstream inference errors using OpenAI's own shape:
This path does not carry a SHROUD_* code. It exists for drop-in OpenAI client compatibility; for the Shroud-native HTTP endpoints (/v1/admin/*, /tma/*) the canonical envelope above applies.
MCP transport (POST /mcp)
MCP returns errors as a tool result with isError: true and the SHROUD code in _meta.errorCode:
JSON-RPC transport (POST /rpc)
The JSON-RPC transport follows the JSON-RPC 2.0 spec: a top-level error object with a numeric code, a human-readable message, and the SHROUD code in error.data.errorCode.
The numeric code follows JSON-RPC conventions: -32601 for unknown tool, -32602 for invalid params, -32603 for tool execution failures. Always read the SHROUD code out of error.data.errorCode rather than parsing the numeric code, because the numeric mapping may evolve.
JSON-RPC protocol-level errors
Envelope-level errors emitted before tool dispatch do not carry a SHROUD code in error.data:
Numeric code | Name | Description |
|---|---|---|
-32700 | Parse Error | Invalid JSON in request body. |
-32600 | Invalid Request | Malformed JSON-RPC envelope or missing method. |
-32601 | Method Not Found | Unknown method, including |
Calling midnight_getBlock directly as a JSON-RPC method returns -32601 Method Not Found at the protocol layer. Use tools.call with {"tool": "midnight_getBlock"} instead.
RPC proxy errors (/v1/midnight/rpc)
The Midnight RPC proxy maps whitelist and upstream-node failures to JSON-RPC errors:
Scenario | Numeric code | Name |
|---|---|---|
Method missing or jsonrpc version invalid | -32600 | Invalid Request |
Method not on the whitelist | -32601 | Method Not Allowed |
Node unreachable / internal proxy error | -32603 | Internal Error |
Upstream node returns an RPC error | passthrough | Forwarded from Midnight node |
The whitelist is per-deployment. Call midnight_listMethods (MCP tool) or read /.well-known/mcp to see which methods are enabled on the deployment you are targeting; see RPC proxy for details.
Cocoon WebSocket (wss://shroud.us/v1/cocoon/stream)
The encrypted Cocoon WebSocket emits a single error frame on stream failure. The shape is set by the Cocoon protocol, not the SHROUD envelope:
Code | Description |
|---|---|
| Requested model is not active on this network. |
(no code) | General error — read |
The Go SDK surfaces this through stream.Err() and the TS SDK through the rejected promise / StreamError class. See Cocoon SDK (Go) and Cocoon SDK (TypeScript).
SDK-level errors
Go SDK (shroud-sdk-go):
stream.Err()returns the error that stopped the stream.Attestation policy failures return errors directly from
Inference().
TypeScript SDK (@shroud/cocoon-sdk-js):
Class | Meaning |
|---|---|
| WebSocket connection or session setup failed. |
| Key derivation, encryption, or decryption failed. |
| TEE attestation verification failed. |
| Server reported an inference error. |
Troubleshooting
401 Unauthorized
Verify your API key format:
shroud_{env}_{32 hex chars}.Check the environment matches the deployment (don't use
shroud_dev_keys against prod).Verify the key hasn't expired or been revoked in the dashboard.
Ensure the
Authorizationheader uses theBearerprefix (capital B, single space).
429 Too Many Requests
Rate limit (Retry-After: 1):
Check your plan's RPS limit (Free = 2, Developer = 10, Startup = 50, Enterprise = 200).
Anonymous (no-key) callers hit a 5 RPS per-source-IP cap; send a key on production traffic.
CU limit (Retry-After: 60):
Read
details.window—24h/30dis per-key, absent is workspace-wide.Monitor usage in the dashboard; raise the per-key limit or upgrade the plan.
MCP tool errors
SHROUD_TOOL_NOT_FOUND— list the deployment's tools atGET /.well-known/mcp.SHROUD_INVALID_PARAMS/SHROUD_SCHEMA_VIOLATION— compare your payload against the tool's input schema in MCP API.SHROUD_TOOL_EXECUTION_ERROR— upstream Midnight node or model worker error; retry with backoff.
Cocoon attestation failures
Make sure you're running the latest SDK with up-to-date image hashes.
If you supply a custom
AttestationPolicy, double-check the allowed hashes match the deployment.Persistent failures may indicate a TEE upgrade — check for SDK releases.
Related
Error codes — auto-generated dictionary of every registered SHROUD code.
Production guide — Error handling map — caller-side action map per code.
Production guide — Rate limits and CU budgets — rate-limit specifics, response headers, worked example.
Authentication — API key formats and Bearer header rules.
Billing — Credit Unit definitions and pricing.