forge
Clone forge-starter
One envelope{ error: { code, message, retry } }
Four retry answersretry · change-input · needs-human · no
MCP is differentJSON-RPC errors ride HTTP 200

Errors

a capability throwsForgeError {code, status, retry}or anything elseone error handlerForgeError → its status + toJSON()else → 500 internal_error · retry: nothe wire{ "error": { "code": "invalid_input", "message": "…", "retry": "change-input", "details": {…} } }status: 400 · 401 · 403 · 404 · 422 · 429 · 503 · 500both planes map errors identically · the retry field tells an agent what to do nextexception: OAuth answers RFC 6749 {error, error_description} · rate limits answer 429 {error: rate_limited, retry_after} + Retry-After
The retry hint is the point: change-input means fix the request, needs-human means stop and ask, retry means try again, no means report it.
codestatusretrywhenwhat the agent says
not_found404change-inputThe requested resource or capability does not exist."There is no app called hello here; did you mean hello-web?"
invalid_input422change-inputThe request input failed schema validation."I need one more thing — every how often, or a cron?"
policy_blocked403needs-humanA governance Policy blocked the operation."This needs Docker on the control plane and it is not available."
permission_denied403needs-humanThe Actor is not authorized to use this Capability or Resource."I am not allowed to do that for this account."
dependency_unavailable503needs-humanA required dependency (Docker, secret, provider) is unavailable."The platform's store is unreachable; I will not retry on my own."
internal_error500noAn unexpected platform error occurred."Something failed inside forge; here is the resource id to report."
rate_limited429per-IP limits on login, signup, /mcp, /oauth/*“Too many attempts — I will wait 30 seconds.”
signature_invalid · webhook_retry400 · 503no · retryStripe webhook signature failed · transient webhook failure

MCP: JSON-RPC errors on HTTP 200

codemeaning
-32600 · -32601 · -32602 · -32603invalid request · method not found · missing/unknown tool · internal
-32001insufficient_scope with data.required_scope — forge-specific
-32011the app's handler is unreachable — forge-specific
(none)a handler non-2xx becomes isError: true in the result, classed handler_status_<code>

A rejected bearer on /mcp is always 401 invalid_token on the wire, deliberately; the real reason lives only on the mcp.auth_reject log line.