Docs / Troubleshooting
Why was I denied?
Every denial the broker can return, what it actually means, and where to fix it. Every one of these is also written to the audit log — the Audit page is the fastest way to see which reason you're hitting.
Identity & authentication
| Reason | What it means | Fix |
|---|---|---|
authentication_required | no user token AND no service key on the request | set KEYWARD_AGENT_KEY (Agents → service key), or pass the user's token |
invalid_user_token | the end-user token didn't verify against the IdP | check the token's issuer/expiry; service mode avoids user tokens entirely |
agent_auth_failed | the service key is wrong or was revoked | issue a fresh key on the Agents page (shown once) and update the env |
unknown_agent | no agent registered with this id — agents are never auto-created | Agents → Register agent; the id must equal KEYWARD_AGENT exactly |
agent_revoked | the agent exists but was revoked | Agents → restore |
agent_attestation_required | the agent is registered as attested but sent no valid workload token | pass agentAssertion (fresh per request), or clear the attestation config |
invalid_delegation | the delegation credential didn't verify or was spliced | pass the orchestrator's unmodified credential; chains are cryptographically bound |
delegation_too_deep | the actor chain exceeded depth 5 | flatten the orchestration — five hops is the ceiling |
agent_attestation_failed | a workload token WAS sent but failed verification (wrong issuer, subject, or expired) | check the attestation issuer / JWKS URI / subject on the agent's registration; mint a fresh token per request |
org_suspended | the tenant is frozen | contact the org owner / support |
unknown_org | the authenticated user belongs to no org | sign up / accept the org invite; membership is required before brokering |
cross_org | the user/delegation and the agent belong to different orgs | use an agent registered in your own org — chains never cross tenants |
Provider & scope
| Reason | What it means | Fix |
|---|---|---|
unknown_provider | no secret for this provider in THIS environment — often an environment mismatch, not a missing key | check the env column on Secrets vs the agent's KEYWARD_ENVIRONMENT; connect the provider if truly missing |
scope_not_allowed | the route's scope isn't in the SECRET's allowed scopes (gate 1 of 2) | Secrets page → the provider's scope checkboxes |
policy_denied | a policy rule denied it, or no allow rule matched (gate 2 of 2 — deny-by-default) | Policies page → add/adjust the allow rule for this agent + provider + scope |
approval_required | a require_approval rule matched and no valid approval existed — the request is queued | an admin approves it on the Approvals page; the agent's NEXT identical call consumes the approval and proceeds (approvals are one-time, and spent at decision time — if the approved call then fails or aborts, re-queue and re-approve) |
route_not_allowed | the provider's catalog doesn't map this method+path to any scope | check the Provider reference for the exact routes; admin/key-management endpoints are excluded by design |
native_not_proxyable | gateway() was called on a native-mode secret | use kw.get(provider, scope, ttl) for native providers |
gateway_provider_unsupported | a proxy secret with no built-in match and no gateway_config | re-connect it as Custom API (base URL + auth header + scope) |
unknown_scope | storing a secret: a scope the provider's catalog doesn't define | pick scopes from the checkboxes — free-typed strings aren't accepted for built-ins |
key_format_rejected | storing a secret: the pasted value is a known-wrong credential kind (webhook secret, admin key…) | paste the right key type — the error message names it |
builtin_name_reserved | a Custom API was named after a built-in provider | pick the built-in from the dropdown, or rename your custom provider |
Limits & upstream
| Reason | What it means | Fix |
|---|---|---|
too_many_requests | per-IP flood cap on the broker | respect retry_after_s; the SDK's cache usually makes this moot |
plan_limit_exceeded | the org hit its plan's secrets cap | remove unused secrets or upgrade the plan |
upstream_unreachable | Keyward couldn't reach the provider's API | usually transient; check the provider's status page |
client_aborted | the CLIENT disconnected mid-call; Keyward cancelled the upstream request | nothing to fix — this is the agent hanging up (interrupted streams, timeouts on the caller's side) |
native_provider_unavailable | the secret's native config names a kind no native provider is registered for | set native_config.kind to a supported kind (aws-sts is the built-in) |
native_mint_failed | the native provider (e.g. AWS STS) refused to mint | check the native config (role ARN, trust policy) on the secret |
Allowed… but the call still failed?
Some providers (Slack) return HTTP 200 with an error inside the body. The gateway detects this and records it in the audit reason as upstream_ok:false <error> — the request was allowed by Keyward and refused by the provider (usually missing bot scopes or the bot isn't in the channel). Fix it on the provider's side; Keyward's gates weren't the blocker.