Transport errors
| Code | Status | Description | Recovery |
|---|---|---|---|
| 307_redirect | 307 | Request hit /mcp without trailing slash. | Always call /mcp/ — many Streamable HTTP clients drop the connection on the redirect. |
| 400_https_required | 400 | Production environment received a non-HTTPS request. | Set ENVIRONMENT=production only behind an HTTPS proxy; otherwise unset ENFORCE_HTTPS. |
| spawn_enoent | — | Inspector configured as STDIO with an HTTP URL as command. | Switch transport to Streamable HTTP. Use the URL field, not Command. |
Authentication
| Code | Status | Description | Recovery |
|---|---|---|---|
| missing_bearer | 401 | Authorization header missing or malformed. | Include Authorization: Bearer <jwt> on every request. |
| invalid_audience | 401 | Token aud != wmstudio-mcp. |
Re-mint via /oauth/token or create_test_token() in development. |
| revoked_token | 401 | Token present in Redis mcp:tokens:revoked. |
Restart the OAuth flow. |
| bad_oauth_state | — | Supabase rejected a stale or duplicated state parameter. | Most often a redirect_to misconfiguration — check the runbook in oauth-fly-supabase-runbook.md. |
Input validation
| Code | Status | Description | Recovery |
|---|---|---|---|
| missing_required | 400 | Required parameter not supplied (e.g. prompt or image_url). |
Check the tool's Parameters table; required params are tagged. |
| asset_url_required | — | A tool that requires a public image/video URL was called without one. | Response includes uploadUrl pointing at the drag-and-drop page. Share the uploadUrl with the user; once they upload, the page returns a CDN URL ready to paste back into the tool. |
| asset_url_required (reason: unreachable) | — | URL provided but failed the HEAD preflight (DNS failure, 404, or non-2xx). Often a fabricated URL. | Never invent URLs. Always use the uploadUrl flow to obtain a real CDN-hosted asset. |
| invalid_image | 400 | Image URL is reachable but not a valid image, or larger than 12MB. | Re-host via the upload page; PNG/JPG/WebP only; max 12MB. |
| unsupported_model | 400 | Model id not enabled on this deployment. | See /docs/configuration#models for the live catalogue. |
| consent_required | 403 | Likeness or Digital Twin call missing consent_acknowledged: true. |
Surface a consent UI in your client and set the flag explicitly. |
Runtime
| Code | Status | Description | Recovery |
|---|---|---|---|
| upgrade_required | 402 | Insufficient credits for this generation. | Response shape: { error: "upgrade_required", reason: "insufficient_credits", upgradeUrl, requiredCredits, availableCredits, message }. Render upgradeUrl as a link to /dashboard/credits and stop calling generation tools until the user tops up. |
| insufficient_credits | 402 | Legacy error code for the same condition as upgrade_required (kept for client compatibility). |
Direct user to /dashboard/credits to top up. |
| rate_limited | 429 | Per-user or per-tool rate window exceeded. | Respect the Retry-After header; back off exponentially. |
| provider_unavailable | 503 | Upstream model provider is temporarily down (fal.ai, OpenAI, etc.). | Retry after 30–60s. The provider is reported in the error body. |
| job_timeout | — | Async job did not finish within its TTL (default 10 min). | Retry with a smaller batch or simpler prompt. |
| job_failed | — | Provider returned a render failure. | Inspect error.message for the provider's reason. |
By tool
Each tool documents its own error shapes — click through for the full table.
Tool-specific error tables are added as edge cases are catalogued.