MAQPNADocs

Error and reason codes

The JSON-RPC codes, the error envelope, every reason the MAQPNA gateway returns, the SDK error for each, and the CLI exit codes.

When the MAQPNA gateway refuses or holds a call, it says why in one envelope with a stable reason. Match on the reason, not on the message text. This page lists the JSON-RPC codes, the envelope, every published reason with the SDK error it becomes and what to do, and the exit codes of the maqpna CLI.

flowchart LR
    G[Gateway decision] --> C{JSON-RPC code}
    C -->|-32001| PD["PolicyDenied (reason: policy_denied, dlp:…, revoked, budget_exceeded:…)"]
    C -->|-32002| AP["ApprovalPending (reason: approval_required)"]
    C -->|-32003| UA["Unauthorized (reason: unauthorized, missing_scope:…)"]
    C -->|-32603| RE["RPCError (reason: audit_unavailable, internal_error)"]
    C -->|-32020 / -32022| PR["HeaderMismatch / UnsupportedProtocolVersion"]

JSON-RPC codes#

Code Meaning Default reason Python / TypeScript Go
-32001 Denied policy_denied PolicyDenied *PolicyDenied
-32002 Held for approval (only when the request carries X-Maqpna-Async: 1) approval_required ApprovalPending *ApprovalPending
-32003 Unauthorized: bad or expired token, or a missing scope unauthorized Unauthorized *Unauthorized
-32020 Model Context Protocol (MCP) revision 2026-07-28: an Mcp-Method, Mcp-Name or MCP-Protocol-Version header does not match the body header_mismatch HeaderMismatch *HeaderMismatch
-32021 MCP 2026-07-28: a client capability the request needs was not declared missing_client_capability RPCError *RPCError
-32022 MCP 2026-07-28: protocol version not supported; data.supported lists the fallbacks unsupported_protocol_version UnsupportedProtocolVersion *UnsupportedProtocolVersion
-32700, -32600, -32601, -32602, -32603 Standard JSON-RPC: parse error, invalid request, method not found, invalid params, internal error parse_error, invalid_request, method_not_found, invalid_params, internal_error RPCError *RPCError

In sync mode (the default) a call that needs approval does not return -32002: the gateway holds it until a person decides, then returns the result or -32001 with approval_denied or approval_expired. See Human approvals.

The error envelope#

Every error the gateway generates carries the same fields in error.data:

Field Meaning
domain Always maqpna.com for gateway errors.
reason <token>[:<qualifier>]. The token is from the table below; the optional qualifier adds machine-readable context: dlp:pan, budget_exceeded:agent/day, missing_scope:tools:github. Match on the text before the first :.
detail Free text when there is more to say, such as the reason text of the rule that denied the call, or approval_denied by reviewer@localhost (apr_…).
policy, rule The policy and rule that decided, when one did. Revocations show revocation/<id>; data loss prevention (DLP) shows policy dlp and the profile name as rule.
others approvalId and expiresAt (-32002), connectURL (consent_required).

Real envelopes from a local MAQPNA (maqpna dev up), as maqpna call prints them:

# a rule denied the call
error -32001: denied by policy baseline-guardrails rule never-touch-system-namespaces: system namespaces are off-limits to agents
data: {"detail":"system namespaces are off-limits to agents","domain":"maqpna.com","policy":"baseline-guardrails","reason":"policy_denied","rule":"never-touch-system-namespaces"}

# an approver denied the held call
error -32001: denied by policy default-agent-policy rule destructive-needs-human: approval_denied by reviewer@localhost (apr_902e3a670541349ffc7844a3)
data: {"detail":"approval_denied by reviewer@localhost (apr_902e3a670541349ffc7844a3)","domain":"maqpna.com","policy":"default-agent-policy","reason":"approval_denied","rule":"destructive-needs-human"}

# the session was revoked with maqpna kill
error -32001: revoked: calls of this token are blocked by revocation/breakglass/51c5fe6e6ada148d (INC-1: test)
data: {"domain":"maqpna.com","policy":"revocation/breakglass/51c5fe6e6ada148d","reason":"revoked","rule":""}

A bad token, as raw JSON-RPC:

{"jsonrpc":"2.0","id":null,"error":{"code":-32003,"message":"unauthorized: identity: malformed token: expected 3 segments","data":{"domain":"maqpna.com","reason":"unauthorized"}}}

A DLP block (the profile is the rule):

data: {"domain":"maqpna.com","policy":"dlp","reason":"dlp:pan","rule":"payments"}

Model route errors#

The model route (/llm/<route>/v1/*) answers OpenAI-style, so OpenAI SDKs raise their normal API errors. type is the error class, code keeps its earlier value for compatibility, and reason is the published token:

{"error":{"code":"route_not_found","domain":"maqpna.com","message":"unknown model route \"nope\"","reason":"route_not_found","type":"maqpna_not_found"}}

The types are maqpna_unauthorized, maqpna_policy_denied, maqpna_approval_required, maqpna_budget_exceeded (HTTP 402), maqpna_rate_limited, maqpna_egress_denied, maqpna_dlp_blocked, maqpna_revoked, maqpna_audit_unavailable, maqpna_upstream_error, maqpna_not_found and invalid_request_error.

Admin API errors#

The admin API (/v1/*, used by the CLI, the console and MAQPNA Desk) answers {"error": "<message>"} for now. Moving it to the same envelope is Planned.

Reasons#

The list is append-only: a reason is never renamed or removed in v1alpha1. The audit ledger uses the same words, so a reason in an error matches the reason in the audit record.

Authentication and authorisation#

These come with -32003 (Unauthorized) on tool calls, or HTTP 401/403 on the model route.

Reason Meaning What to do
unauthorized Missing, invalid or insufficient credentials (default of -32003). Check that the agent sends the session token (MAQPNA_TOKEN_FILE or MAQPNA_TOKEN). Inspect it with maqpna token inspect.
missing_token No bearer token. Run the agent under maqpna dev run, or check the sandbox's token mount.
invalid_token Token malformed or not verifiable. Mint a new token; check the gateway trusts the broker's public keys (JWKS).
token_expired The token has expired. The SDKs re-read the token file; make sure the operator can re-mint it. Locally, raise maqpna dev run --ttl.
token_signature_invalid Signature invalid or unknown signing key. Check key rotation: maqpna token verify TOKEN --jwks URL.
token_audience_mismatch Wrong aud. Mint for audience maqpna-gateway.
missing_scope The token lacks the scope, for example missing_scope:tools:github. Add the MCP server to the agent's tools (Agent.spec.tools), or the scope to maqpna dev run --scope.
insufficient_scope An external client token lacks a step-up scope. Ask the user to re-authorise with the scope.
header_mismatch An identity header does not match the token, or an MCP header does not match the body (-32020). Do not set X-Maqpna-* identity headers yourself; let the SDK build the MCP headers.
principal_unverified The user the agent acts for could not be verified. Check the session's user assertion and the identity provider configuration.
svid_invalid, svid_required, svid_trust_domain, svid_mismatch Workload identity (SPIFFE) client certificate problems. Check the SPIRE setup and tls.svidMode.
tenant_mismatch The token's key or trust domain belongs to another tenant. Mint the token with the tenant's own broker key.

Policy#

These come with -32001 (PolicyDenied).

Reason Meaning What to do
policy_denied A rule denied the call; its text is in detail, the rule in rule. Read the rule; test a change with maqpna policy test. See Write policies.
no_applicable_policy No policy applies to this agent and namespace (default deny). Create a ToolPolicy that selects the agent.
default_action No rule matched and the policy's defaultAction decided. Add a rule for the tool, or change the default.
rate_limited maxCallsPerMinute or tokensPerMinute was exhausted. Back off and retry; raise the limit in the rule if it is too low.
revoked A revocation (kill switch) matches the agent, session, user or token. Find it with maqpna revocations list. See Kill switch and revocations.
revocation_list_unavailable The gateway cannot read the revocation list, so calls are denied. Check the gateway's revocation file or state backend; maqpna doctor.
budget_exceeded A budget is used up; qualifier <scope>/<window>, for example budget_exceeded:agent/day. Wait for the window to reset or raise the budget. See Budgets and cost limits.
dlp A DLP profile found sensitive data; qualifier is the detector, for example dlp:pan, dlp:iban, dlp:github_token. Remove the data from the arguments, or change the profile. See DLP profiles.
guard A prompt-injection guard flagged the content; qualifier <guard>:<label>. See Taint and prompt-injection containment.
guard_unavailable The guard is unreachable and failOpen is false, so calls are denied. Check the guard service.
tool_definition_changed The tool's definition changed after it was pinned (drift). Review the change, then re-pin with maqpna mcp pin. See MCP servers and tool pinning.
tool_unpinned The tool is not pinned and unpinned tools are denied. Pin it.
tool_definition_unverified The tool definition could not be verified. Check the MCP server and its pins.
cedar_unavailable A Cedar policy exists but this gateway was built without Cedar support. Use a gateway build with Cedar, or rewrite the rule.
cedar_error Cedar evaluation failed, so the call is denied. Check the policy with maqpna policy lint.
rego_unavailable, external_policy_error The external policy engine (OPA or an adapter) failed, so the call is denied. Check the engine's health and timeout.
egress_denied The destination is outside the egress or residency policy. Allow the host in the policy, if it is allowed in your jurisdiction.
model_not_allowed_for_data_class The model route is not allowed for the session's data class. Use a model route approved for that data class.

Approvals#

Reason Code Meaning What to do
approval_required -32002 Held for a person (async mode). data.approvalId, data.expiresAt. Poll with wait_for_approval / waitForApproval / WaitForApproval, or tell the user.
approval_denied -32001 An approver denied the call; detail names the approver and the approval. Do not retry the same call; change the plan.
approval_expired -32001 Nobody decided before the approval expired. Retry to queue a new approval, or ask approvers to watch the queue (maqpna approvals watch).
approval_invalid -32001 The X-Maqpna-Approval-Id does not belong to this exact call. An approval covers exactly one identical call; queue a new one.
approval_aborted -32001 The approval wait was aborted. Retry.
approval_required_not_supported_for_egress, approval_required_unsupported_for_models -32001 A rule asks for approval on egress or a model call, which cannot wait. Use allow or deny for those, and approvals for tool calls.
user_confirmation_unavailable -32001 User approval on their own device (CIBA) could not be asked, and the fallback denied the call; for example user_confirmation_unavailable:ciba_rejected. Check the CIBA configuration and the user's device.
ciba_rejected -32001 The user rejected the request on their device. Respect the decision.
ciba_unavailable -32001 The CIBA request could not be sent. Check the identity provider's CIBA endpoint.

Routing and resources#

Reason Meaning What to do
unknown_server No MCP server of that name is visible to the caller (-32003). Check the name with maqpna mcp list and the agent's tools.
ambiguous_server The name matches several MCP servers. Use a unique server name.
cross_tenant_server The server belongs to another tenant. Use a server in your tenant's namespaces.
route_not_found Unknown model route. Check the route name in MAQPNA_MODEL_ENDPOINT.
route_namespace_not_allowed, namespace_not_allowed The model route is not allowed for this namespace. Allow the namespace on the route.
route_agent_not_allowed, agent_not_allowed The model route is not allowed for this agent. Allow the agent on the route.
consent_required The user must connect the provider first; data.connectURL has the link (-32001). Send the user to connectURL, then retry.
per_user_unavailable Per-user credentials are not configured. Configure the token vault for the provider.
memory_backend_unavailable The memory store backend is unavailable. Check the memory store.

Agent-to-agent (A2A)#

Reason Meaning
unknown_agent The A2A callee is unknown.
caller_not_allowed The caller is not in the callee's allowedCallers.
unknown_skill, unknown_method The skill or method does not exist.
delegation_depth The delegation chain is too deep.
delegation_loop The delegation loops back to an earlier agent.
callee_revoked The callee is revoked.
peer_card_unverified The remote peer's agent card signature could not be verified.

Availability#

These usually come with -32603 (RPCError), or TransportError when the gateway's answer is not JSON-RPC.

Reason Meaning What to do
audit_unavailable auditFailurePolicy: closed and the gateway could not write the audit record, so it refused the call. Check the ledger volume or the Postgres state backend: maqpna doctor.
upstream_unavailable The MCP server or model could not be reached. Check the upstream; retry with backoff.
upstream_credential_unavailable The credential for the upstream is missing. Check the referenced Secret.
upstream_error The upstream failed. See the upstream's logs.
egress_dial_failed, egress_upstream_failed The egress proxy could not connect, or the destination failed. Check DNS and the destination.

Protocol#

Reason Meaning
parse_error Invalid JSON (-32700).
invalid_request Invalid JSON-RPC request (-32600).
invalid_params Invalid params (-32602).
method_not_found Unknown method (-32601).
internal_error Internal error (-32603), and any error without a reason.
invalid_body, invalid_json The model-route request body could not be read, or is not JSON.
unsupported_protocol_version -32022: the gateway, or the MCP server's declared protocolVersions, does not support the revision; data.supported lists the fallbacks. The SDKs fall back automatically with protocol="auto".
missing_client_capability -32021: the request needs a client capability that was not declared.

CLI exit codes#

Every maqpna command (and the maqpna-install plugin) uses the same exit codes, so scripts and CI can branch on them:

Exit code Meaning Examples
0 Success. A call was allowed; audit verify found the chain intact.
1 Error: the action did not happen. Gateway unreachable, file not found, HTTP 404 from the admin API.
2 Usage error, including a destructive command run without a terminal and without --yes. An unknown flag; maqpna kill in CI without --yes.
3 A check failed, or the gateway refused the call. maqpna call denied by policy, DLP or a revocation; maqpna audit verify found tampering; maqpna policy test --expect mismatch.
128+N The maqpna-install plugin died of signal N. —

maqpna dev run exits with your command's exit code. For example, a denied maqpna call under it:

maqpna dev: session dev-0cf86530 (agent coder, namespace dev, on behalf of you@localhost)
error -32001: denied by policy baseline-guardrails rule never-touch-system-namespaces: system namespaces are off-limits to agents
data: {"detail":"system namespaces are off-limits to agents","domain":"maqpna.com","policy":"baseline-guardrails","reason":"policy_denied","rule":"never-touch-system-namespaces"}
maqpna dev: dev-0cf86530: 1 deny, cost $0.0000 (maqpna dev timeline --last)
$ echo $?
3

Next: Python SDK, Troubleshooting.