Errors

Look up the shape of an error response on each surface, what every error code means and what to do about it.

AuthFI reports a failure in the shape that the surface's standard defines. Find the surface you called, then the code.

Response shapes

SurfaceShape
OAuth endpoints and the agent token endpointOAuth 2.0 (RFC 6749): error, and sometimes error_description
The authorization endpointThe same fields, with state, in the query string of the redirect URI
Other endpointsA code in error, with the matching HTTP status
Zero-Code403 with error, message and ref
MCP gatewayA JSON-RPC error, or a tool result with isError set

An OAuth error:

{ "error": "invalid_client", "error_description": "client authentication failed" }

An error from another endpoint:

{ "error": "invalid_body" }

A successful response from those endpoints puts its result under data:

{ "data": { "decision": "allow" } }

OAuth endpoints for applications

These codes come from the endpoints under /oauth/. Each endpoint is described in OAuth and OpenID Connect endpoints.

errorStatusMeaningWhat to do
invalid_request400A parameter is missing or malformedSend every required parameter. Register the exact redirect URI, with path and port.
invalid_client401The client is unknown, or its secret is wrongCheck the client ID, the issuer and the client secret
invalid_grant400The code or refresh token is wrong, expired or already usedStart a new sign-in. Exchange each code once, within 5 minutes.
unauthorized_client400This application may not use this grantUse an m2m application for client_credentials
unsupported_grant_type400The grant type is not one the endpoint offersUse authorization_code, refresh_token or client_credentials
invalid_scope400A refresh asked for more than was grantedAsk for a subset of the scopes first granted
invalid_target400resource is not something this caller may addressName the API's client ID, and grant the caller access to that API
access_denied403The person is not assigned to the applicationAssign the application to the person or one of their groups
login_required401The session is too old for prompt=login or max_ageSend the person to sign in again
interaction_required401The person must complete another stepSend the person to the sign-in page
unmet_authentication_requirements400The acr_values asked for could not be reachedEnrol the person in MFA or a passkey, or ask for a lower value
insufficient_user_authentication401A stronger sign-in is needed before this token can be issuedSend the person to sign in with the acr_values required
temporarily_unavailable503The request could not be handled right nowTry again shortly
forbidden403The project's plan or account does not allow thisChange the plan
rate_limited429Too many attemptsWait, then send fewer requests

Presenting a used refresh token revokes every refresh token from the same sign-in and returns invalid_grant. See Refresh tokens.

Guides that use these codes: Add sign-in to an app, Sessions, Application types and Service to service.

Agent token endpoint

These are the only values error takes at /apis/regional/v1/ai/auth/token, so your code can branch on them.

errorMeaningWhat to do
invalid_requestThe body could not be read, or a field is missingSend the body form-encoded, with every required field
invalid_clientThe agent is unknown or revoked, or its assertion did not verifyCheck kid, aud, the clock, and that jti is new
invalid_grantThe grant is not valid for this clientCheck grant_type and what was sent with it
unauthorized_clientThis client may not use this grantUse a grant the agent may use
unsupported_grant_typeThe grant type is missing or not one the endpoint offersUse client_credentials
invalid_scopeA requested scope is not allowedRemove the scope from the request
invalid_targetresource names something this agent has not been grantedAsk an administrator to grant the agent access to that target
temporarily_unavailableThe grant could not be checked right nowTry again shortly

An assertion is accepted once. Sending the same one again returns invalid_client. See Give an AI agent an identity and Accept agents at your own API.

Four more codes apply while an agent polls for a person's answer with the CIBA grant. Each has the status 400. See Ask a named person.

errorMeaningWhat to do
authorization_pendingThe person has not answeredWait interval seconds, poll again
slow_downYou are polling too fastWait longer between polls
access_deniedThe person denied the requestStop
expired_tokenThe request expired before anyone answeredStop, or ask again

Other endpoints

Endpoints outside OAuth return a code in error with the matching HTTP status.

StatuserrorMeaningWhat to do
400invalid_bodyThe request body is missing a field or is not valid JSONSend valid JSON with every required field
401unauthorizedNo credential, or one that is expired or revokedGet a new credential and send it
403The caller is known and is not allowed to do thisGrant the caller access, or check the plan
404Nothing with that identifier exists in this projectCheck the identifier and the issuer
429More than 300 requests a minute from one IP addressWait, then send fewer requests

Some endpoints use these statuses for a specific cause.

EndpointStatusCauseGuide
/saml/…403The plan does not include SAML single sign-onConnect a SAML application
/saml/sso403The sign-in request failed validationConnect a SAML application
/scim/v2/…403The plan does not include SCIMProvision people with SCIM
/scim/v2/…401The SCIM token has expiredProvision people with SCIM
/v1/auth/resolve404No connection claims that email domainSign in with another identity provider
Agent authorize and approvals401The agent is unknown or revokedLimit what an agent may do

Decisions

A decision is a successful response, not an error. The authorize endpoint returns decision and reason under data. See Limit what an agent may do.

{ "data": { "decision": "deny", "reason": "constraint_violated: amount max" } }
decisionreasonMeaningWhat to do
allowresource_grant, relationshipSomething granted itGo ahead
denyno_matchNothing granted itStop. To allow it, give the agent a role that carries the permission.
denypolicy_denyA rule denies itStop
denyconstraint_violated: …A limit on the capability was exceededStop, or ask within the limit
approval_requiredpolicy_step_upA rule sends it to a personPoll with approval_id

An approval that nobody answers reaches the status expired. Treat it as denied. See Ask before a sensitive action.

Zero-Code denials

A request denied at the node returns 403 with a reference that identifies the denial in the audit record.

HTTP/1.1 403 Forbidden
WWW-Authenticate: Bearer realm="authfi", error="invalid_token"
X-Authfi-Ref: 7c1f0a2e
Content-Type: application/json

{ "error": "authfi_audience_mismatch", "message": "This credential was issued for a different service.", "ref": "7c1f0a2e" }

The checks run in this order on each request to a protected API. See Protect an API.

Denied asMeaningWhat to do
missing_tokenThe request has no Bearer tokenSend an access token as Authorization: Bearer
invalid_tokenThe token is not signed by your project, has expired, or its agent or session was revokedGet a new access token
not_an_access_tokenThe token is an ID tokenSend the access token
audience_mismatchThe token was issued for another APIAsk for a token with resource set to this API's client ID
policy_deniedThe route's rule is not metGive the caller what the rule requires, or change the rule

Other callers are answered differently. See Protect a service with no code and Enforcement in the kernel.

CallerResponseWhat to do
A browser with no sessionA redirect to the sign-in pageSign in
A person not assigned to the applicationA 403 page that says soAssign the application to the person or a group
A workload connecting where it was not grantedThe connection fails with EPERMAdd the destination and port to the workload's list
Any caller, when the node agent has no rules yet503 with Retry-AfterRetry after the time given

In monitor mode nothing is denied. Each request that would have been denied is recorded with its reason.

MCP gateway

The MCP gateway reports a failure at one of three levels. See The MCP gateway.

HTTP. A request with no token, or one that is expired or revoked, returns 401 with a pointer to the protected resource metadata.

HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer resource_metadata="https://acme.authfi.io/.well-known/oauth-protected-resource"

JSON-RPC. A request the gateway cannot process returns a JSON-RPC error.

CodeMeaningWhat to do
-32700The body is not valid JSONSend valid JSON
-32601The method is not initialize, tools/list or tools/callUse one of the three methods
-32602The parameters are wrongCorrect params and send the request again
-32000The tool server could not be reachedCheck the server's URL in the console, then retry

Tool result. A denied call is an ordinary tool result with isError set, so the model reads it and can change course.

{
  "jsonrpc": "2.0",
  "id": 7,
  "result": {
    "isError": true,
    "content": [{ "type": "text", "text": "Denied by policy: agent:agt_7f3a9c21 is not granted payments.refund" }]
  }
}
Result text beginsMeaningWhat to do
Denied by policyThe gateway denied the call. The text gives the reason.Grant the tool, or change the arguments
Approval requiredA rule sends the call to a personAfter approval, repeat the call with _authfi_approval_id

An approval is good for 15 minutes and for that call. A call to a tool with per-person credentials is denied when no person is named, or when the person has not connected their account.