> ## Documentation Index
> Fetch the complete documentation index at: https://onecli.sh/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Gateway Errors: Proxied Request Failures

> Every JSON error body the gateway returns on proxied agent traffic, with status codes, remediation links, and which responses are safe to retry.

Agent traffic rides the gateway proxy transparently, so when the gateway blocks or can't route a request, the error arrives on the agent's ordinary HTTP call to the provider — not on the management API. These bodies are flat JSON objects with an `error` code (distinct from the management API's [error envelope](/docs/api-reference/errors)), and each one tells the agent what to do next, usually with a pre-built dashboard link.

Every definite verdict carries the `x-should-retry: false` header: retrying unchanged will not succeed — the fix is the named remediation. Only the transient responses omit it: `gateway_restarting`, `rate_limited`, and the 502 internal errors.

## Summary

| `error`                                                            | Status           | Meaning                                                       | Retry?              |
| ------------------------------------------------------------------ | ---------------- | ------------------------------------------------------------- | ------------------- |
| `multiple_connections`                                             | 409              | Several accounts of the same app match — name one             | With the header     |
| `multiple_providers`                                               | 409              | Accounts of different apps match — name one                   | With the header     |
| `connection_not_found`                                             | 404              | The named connection id is stale — re-pick                    | With a new id       |
| `access_restricted`                                                | upstream 401/403 | A credential exists, but this agent has no grant for it       | No — grant first    |
| `app_not_connected`                                                | upstream 401/403 | No account of this app is connected at all                    | No — connect first  |
| `credential_not_found`                                             | upstream 401/403 | Unknown host with no credential configured                    | No — add a secret   |
| `blocked_by_policy`                                                | 403              | A policy rule blocked the request                             | No                  |
| `blocked_by_default_policy`                                        | 403              | Nothing allowed the request (deny-by-default)                 | No                  |
| `app_unavailable`                                                  | 403              | The app is outside the organization's availability allowlist  | No                  |
| `resource_access_denied`                                           | 403              | A session policy restricts this connection to named resources | No                  |
| `manual_approval_denied`                                           | 403              | A human denied the request, or the approval timed out         | No                  |
| `gateway_restarting`                                               | 503              | The gateway restarted while holding the request for approval  | **Yes**             |
| `rate_limited`                                                     | 429              | A policy rule's rate limit was hit                            | After `retry-after` |
| `resolution_failed` / `bad_gateway` / `approval_store_unavailable` | 502              | Gateway internal error                                        | Brief backoff       |
| `quota_exceeded` / `budget_exceeded` / `claim_required`            | 429 / 403        | Cloud plan or partner limits                                  | No — plan action    |

The two 409s and the 404 belong to the [multiple accounts protocol](/docs/api-reference/multi-account), which documents their bodies and the `x-onecli-connection-id` retry contract in full.

## Access errors

### `access_restricted`

A credential for this host exists in the project, but the requesting agent holds no [grant](/docs/guides/agent-access) for it. The upstream 401/403 status is preserved; `manage_url` opens the app's connections page, where each account's **Agent access** dialog attaches it to agents.

```json theme={null}
{
  "error": "access_restricted",
  "message": "Gmail credentials exist in OneCLI but this agent does not have access. Ask the user to attach the account to this agent: https://app.onecli.sh/connections/apps/gmail",
  "provider": "gmail",
  "manage_url": "https://app.onecli.sh/connections/apps/gmail"
}
```

### `app_not_connected`

The host belongs to a known app, but no account of it is connected. `connect_url` opens the connect flow. A second variant covers known API hosts with no registered provider (for example an unregistered Google API on `www.googleapis.com`) — it carries `hostname` instead of `provider` and its `connect_url` opens the "Request an app" dialog.

```json theme={null}
{
  "error": "app_not_connected",
  "message": "Gmail is not connected in OneCLI. Ask the user to open this URL to connect it: https://app.onecli.sh/connections?connect=gmail",
  "provider": "gmail",
  "connect_url": "https://app.onecli.sh/connections?connect=gmail"
}
```

### `credential_not_found`

The host is not a known app and no secret matches it. `secret_url` is a pre-built create link with the host and path pre-filled; the message documents query parameters the agent can append before handing it to the user — `&name=` for a display name, `&header=` / `&format=` to describe a custom auth header, or `&param=` for query-parameter auth.

```json theme={null}
{
  "error": "credential_not_found",
  "message": "No credentials configured for api.stripe.com in OneCLI. A pre-built link is provided in the `secret_url` field. ...",
  "hostname": "api.stripe.com",
  "path": "/v1/charges",
  "secret_url": "https://app.onecli.sh/connections/custom?create=generic&host=api%2Estripe%2Ecom&path=%2F%2A"
}
```

## Policy errors

### `blocked_by_policy`

A named rule blocked the request. At project scope the block comes from the agent's own grant (changeable on the agent's pages); an organization rule's block can only be changed by an org admin. `dashboard_url` opens the agents page.

```json theme={null}
{
  "error": "blocked_by_policy",
  "message": "Blocked by OneCLI policy rule \"Never delete repos\". DELETE /repos/acme/api is not allowed. Review this agent's access in your OneCLI dashboard.",
  "rule_name": "Never delete repos",
  "method": "DELETE",
  "path": "/repos/acme/api",
  "dashboard_url": "https://app.onecli.sh/agents"
}
```

### `blocked_by_default_policy`

No rule matched under a deny-by-default posture — there is no `rule_name` because no rule decided; the request failed because nothing allowed it. The usual fix is attaching the credential the agent needs.

```json theme={null}
{
  "error": "blocked_by_default_policy",
  "message": "A default-deny policy blocked this request. POST api.stripe.com/v1/charges is not permitted for this agent. Attach the credential it needs, or ask an organization administrator to allow the destination.",
  "method": "POST",
  "host": "api.stripe.com",
  "path": "/v1/charges",
  "dashboard_url": "https://app.onecli.sh/agents"
}
```

### `app_unavailable`

The organization's app-availability allowlist excludes this app for the project. Only an organization admin can change availability, so there is no per-project link.

### `resource_access_denied`

A session policy on the connection restricts which resources it may touch (for example, GitHub `{"repositories": ["acme/api"]}`), and the request targeted something outside the list.

## Approval errors

### `manual_approval_denied`

A request held for [manual approval](/docs/guides/rules#manual-approval) was denied by the reviewer, or expired unanswered. `approval_id` identifies the decision in the audit log.

```json theme={null}
{
  "error": "manual_approval_denied",
  "message": "This request was denied by an OneCLI manual approval policy.",
  "approval_id": "apr_7b2e91"
}
```

### `gateway_restarting`

The gateway shut down while holding the request for approval. Nobody decided anything — this is deliberately **not** the 403 a denial produces, so agents don't stop retrying something that was never refused. It is the one gateway error that is safe to retry as-is; a `retry-after: 1` header is set.

```json theme={null}
{
  "error": "gateway_restarting",
  "message": "OneCLI gateway is restarting and released this request before it was reviewed. Retry it.",
  "approval_id": "apr_7b2e91"
}
```

## Limit errors

### `rate_limited`

An allow rule's rate limit was hit. Retry after the `retry-after` header (seconds); `limit` echoes the cap.

```json theme={null}
{
  "error": "rate_limited",
  "message": "This request was rate-limited by an OneCLI policy rule.",
  "limit": 100,
  "window": "hour"
}
```

### Cloud plan limits

On OneCLI Cloud, three additional errors can appear: `quota_exceeded` (429 — the plan's monthly integration-call quota), `budget_exceeded` (429 — a partner-set spend cap on an LLM key), and `claim_required` (403 — the organization must be claimed before this credential can be used). Each message states the exact limit and the action to take.

## Handling in code

The [Node SDK](/docs/sdks/node) ships typed interfaces for these bodies and a `parseGatewayError` helper that narrows an unknown response body to the right shape — see the SDK reference for a retry example.

## Related

* [Multiple accounts](/docs/api-reference/multi-account) — the 409/404 disambiguation protocol
* [API errors](/docs/api-reference/errors) — the management API's error format and retirement inventory
