---
title: "Troubleshooting"
description: "The failures you are most likely to hit, what causes them and the fix for each."
image: "https://docs.agentregistrar.dev/og/docs-default.png"
---

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

# Troubleshooting

Errors come from three places: the MCP transport, the broker tools, and the provider. A transport failure is the exception: an unauthenticated request gets a bare JSON-RPC error with a code and a message, and nothing else. The broker tools return a structured envelope with a stable code, a `retryable` flag and the side effects that did or did not happen. Read the code, not the prose.

## OAuth and the connection

| Symptom | Cause | Fix |
| :--- | :--- | :--- |
| The browser did not open | The client could not launch a browser, or the session is headless | Copy the authorization URL the client printed and open it yourself |
| Signed in as the wrong GitHub account | The OAuth session decides the human, not the email you typed | Sign out of the client's session, sign out of GitHub, reconnect |
| `401` with a `WWW-Authenticate` header | The bearer token is missing, expired or revoked | Re-run the client's OAuth step |
| `403` "Master Agent Delegation ToS has not been signed" | The human has not signed the agreement | Sign it in onboarding, then reconnect |
| `403` "Human owner account is suspended" | The human account is suspended | Contact the security address in the site footer |
| Tools disappear after a while | The client dropped the session or the token expired | Reconnect; the agent identity is resumed, not recreated |

The MCP endpoint returns `401` for an unauthenticated request with a JSON-RPC error and a `WWW-Authenticate` challenge. That is the expected first response, not a broken server.

## Registration

| Symptom | Cause | Fix |
| :--- | :--- | :--- |
| `identity_register` returns an agent you did not just create | The session is bound to the agent it registered; that token-bound agent wins over `name` | Expected. Start a new OAuth session and use a different `name` for a distinct identity |
| `agent_revoked` | The sub-identity is blocked | Reactivate it in the portal, or register a different name from a new session |
| `internal_error` | Broker or database failure | Retry; registration is idempotent |

## Prove and record

| Code | Retryable | Cause | Fix |
| :--- | :--- | :--- | :--- |
| `human_email_unverified` | no | The human has not verified the email | Verify it in onboarding |
| `master_tos_unsigned` | no | The master agreement is unsigned | Sign it in onboarding |
| `human_suspended` | no | The human account is suspended | Contact the security address |
| `agent_revoked` | no | The kill switch is on | Reactivate, or use a new identity |
| `scope_not_granted` | no | `requested_scopes` includes something the agent does not hold | Request only delegated scopes |
| `tos_text_hash_mismatch` | no | The text you sent does not hash to the hash you sent | Re-read `terms.text`, recompute the hash, send the exact bytes |
| `ledger_email_failed` | yes | The acceptance was recorded but the receipt did not send | Retry the same call; only the mail is retried |
| `signup_token_invalid` | no | The receipt failed verification | Get a valid token from the provider |
| `signup_token_not_linked` | no | The receipt references an acceptance this broker has not recorded | Run `identity_prove` for that audience, then retry |
| `signup_token_ownership_mismatch` | no | The receipt belongs to another human | Stop; use the token for your account |
| `internal_error` | yes | Broker failure | Retry with the same inputs; check `side_effects.assertion_minted` |

Two habits prevent most of these. Send the terms text exactly as received, with no trimming or re-wrapping. And retry the same call rather than a new one: an identical `identity_prove` cannot create a second acceptance.

## Discovery

| Symptom | Cause | Fix |
| :--- | :--- | :--- |
| `404` or `410` on `/.well-known/agent-signup.json` | The service does not support the protocol | Stop. This is not a retryable error |
| The document parses but `protocol` is different | Another protocol or a malformed document | Treat the service as unsupported |
| `issuer_allowlist` does not contain your broker origin | The provider does not accept this broker | Do not proceed; tell the human |
| `required_scopes` is not covered by the agent's scopes | The provider asks for more than was delegated | Ask the human to re-delegate; do not proceed |
| The recomputed hash differs from `terms.sha256` | The document and the terms disagree | Stop. Re-fetch; if it still differs, report it to the provider |
| The document advertises SKUs, provisioning or quotas | Non-conformant vendor capability in discovery | Do not rely on those fields; report it to the provider |

## Signup at the provider

The specification fixes one error set for relying parties. `error_description` is for humans and must not drive control flow; use `error` and, when present, `retryable`. A provider that returns a different code is not conformant; report it rather than guessing.

| Code | HTTP | Meaning | Action |
| :--- | :--- | :--- | :--- |
| `invalid_request` | 400 | Malformed headers or body | Fix the request; do not retry blindly |
| `invalid_assertion` | 401 | Signature or shape failed | Mint a new assertion |
| `issuer_not_allowed` | 403 | `iss` is not in the allowlist | Stop; this broker is not accepted |
| `audience_mismatch` | 403 | `aud` does not equal `audience` | Re-discover and mint for the right audience |
| `assertion_expired` | 401 | `exp` passed | Mint a new assertion |
| `assertion_replayed` | 409 | The `jti` was used in a conflicting context | Mint a new assertion; do not reuse |
| `tos_hash_mismatch` | 409 | The accepted hash is stale | Re-discover, re-read, re-prove, then retry |
| `insufficient_scope` | 403 | A required scope is missing | Ask the human to re-delegate |
| `human_unverified` | 403 | `human.verified` is not true | Verify the human email |
| `rate_limited` | 429 | Throttled | Back off for the advertised delay |

A `resolution: "resolved"` response is a success, not an error. A provider that returns no credential on resolve is behaving correctly.

## Inbox

| Symptom | Cause | Fix |
| :--- | :--- | :--- |
| `wait_timeout` | Nothing matched inside the lookback window or the budget | Raise `since_seconds_ago`, check the filters, or call `inbox_list` first |
| A message exists but the wait missed it | The filter is a substring of the raw address or subject | Match on `subject_contains` or a domain fragment that appears in the raw value |
| `message_not_found` | The id belongs to another agent, or no longer exists | List the inbox and use an id from the result |
| `detected_otp` is `null` | No standalone six-digit number in the subject or body | Read the body; the code may be split or formatted differently |
| Two forwarded receipts for one signup | Two acceptances exist, for example a changed terms hash or `force_new` | Check the ledger; the fix is to stop calling `force_new` |
| `send_failed` | The outbound provider rejected the message | Nothing was sent; retry once, then investigate |

## A lost credential

Do not re-run signup. A resolve returns no credential. Use the provider's rotation path, described in [Credentials and recovery](/agents/credentials-and-recovery/).

## Where to get help

- Security issues in the broker, the protocol or these docs: `security@agentregistrar.dev`.
- Documentation and specification defects: [the specification repository issues](https://github.com/agentregistrar/spec/issues).
- Provider-side problems: the provider's own support and security contacts, which its discovery document or guide should name.

Source: https://docs.agentregistrar.dev/agents/troubleshooting/index.mdx
