Error Reference
Every error a caller can receive from the x1id SDK and REST API, what it means, and what a UI should do about it.
Error Reference
Both the SDK (@x1id/resolve) and the REST API surface a small, fixed set of
error conditions. Neither ever falls back to guessing a namespace or returning
a plausible-but-wrong address — an unresolved or ambiguous query is always an
error, never a best-effort answer.
ambiguous is a security property, not an edge case
When a query's text matches both the @handle shape and a known domain shape
at once (for example @jack.x1), x1id refuses to resolve it rather than
picking one. @jack and jack.x1 can be owned by different people. A UI must
surface this to the user and ask them to disambiguate — it must never retry
with one namespace stripped, never "try handle first, then domain," and never
resolve to whichever namespace happens to have a registered record.
SDK errors (ResolveError)
resolve() and reverse() throw a ResolveError with a code field from a
fixed union — never a bare string — so a UI can branch on it directly instead
of parsing a message.
code | Meaning | What a UI should do |
|---|---|---|
unrecognized | The input isn't a handle or a known domain shape at all — it's probably a raw address or unrelated text. | Don't show a resolution error. This is the expected result of running looksLikeName() against arbitrary input (e.g. a pasted base58 address); skip resolution and treat the input as a literal address instead. |
ambiguous | The input matches both the @handle shape and a domain shape at once (e.g. @jack.x1). | Stop. Ask the user to clarify which namespace they mean (a plain @jack, or jack.x1). Never auto-resolve either interpretation. |
invalid-handle | Right shape (@-prefixed), but the content fails handle validation (bad characters, length, etc.) | Show a normal "not a valid handle" validation message, same tier as any other malformed-input error. |
invalid-domain | Right shape (dot + known TLD), but the label fails domain validation. | Show a normal "not a valid domain" validation message. |
not-found | The name is well-formed and in the correct namespace, but nothing is registered under it. | Show "not registered" — distinct from an invalid-input error. This is a legitimate terminal state, not a retry case. |
no-record-for-chain | The name resolves, but has no record for the specific chain requested (e.g. asking for an ETH or BTC address today). | Show "no address on file for this chain" rather than any address. Per-chain ETH/BTC records are on the roadmap — this code exists precisely so a caller never receives a wrong address for an unsupported chain. |
rpc-error | Transport failure — the RPC endpoint was unreachable, returned a non-2xx status, or returned a malformed/short account that couldn't be parsed. | Treat as transient. Safe to retry with backoff; do not treat it as "not found." |
ResolveError also carries the original input string where available, for
error messages that echo back exactly what the user typed.
REST API errors
The REST API (GET /resolve/:name) returns the same underlying conditions as
plain HTTP status codes with a JSON { "error": "...", "input": "..." } body.
It is a read-only convenience over the same on-chain data the SDK reads — see
REST API for the full endpoint contract.
| HTTP status | error message | Meaning | What a caller should do |
|---|---|---|---|
409 | ambiguous: both a handle and a domain shape | Same condition as the SDK's ambiguous — the input matches both namespace shapes. | Same as above: refuse to guess, ask the caller/user to disambiguate. Never treat a 409 as retryable or resolvable by picking one namespace. |
400 | invalid handle | @-shaped input fails handle validation. | Equivalent to the SDK's invalid-handle — treat as a validation error. |
400 | invalid domain | Domain-shaped input fails domain parsing. | Equivalent to the SDK's invalid-domain. |
400 | bad name | Domain parsed but account derivation failed. | Treat as a validation error, same tier as invalid domain. |
404 | handle not registered | Well-formed @handle, nothing registered. | Equivalent to the SDK's not-found. |
404 | domain not registered | Well-formed domain, nothing registered at that account. | Equivalent to the SDK's not-found. |
404 | account is not under the claimed TLD | The derived account exists but isn't actually parented under the TLD it claims — a defensive check, not expected in normal operation. | Treat as not-found. Do not surface the underlying account data. |
404 | not found | Unknown route (not a /resolve/:name, /health, or /version path). | Client/integration bug — check the request path. |
405 | method not allowed | Non-GET request. The API is read-only by construction: there is no write path, no key, no mutation endpoint. | Client/integration bug — use GET. |
502 | malformed account | The account was fetched but its data doesn't match the expected on-chain layout. | Treat as transient/infrastructure error, same tier as the SDK's rpc-error. Safe to retry. |
The REST API is not a source of truth
Every answer the REST API gives is also derivable by reading chain directly — that's exactly what the SDK does. If a caller ever needs to double-check a REST API response (or the API is unreachable), the same account can be read directly over RPC using the derivation rules in the on-chain reference.
General guidance
- Never render a bare address. Every successful result — from the SDK or the REST API — carries the namespace that produced it. Show the namespace next to the address in any confirmation UI.
- Treat
ambiguousas blocking, not as a fallback chain. Don't retry the same input against "just the handle namespace" or "just the domain namespace" after seeingambiguous— that reintroduces exactly the wrong-recipient risk the error exists to prevent. not-foundandno-record-for-chainare not failures to retry. They're correct, final answers about the current state of the registry. Retrying won't change the result unless the underlying registration changes.- Transport errors (
rpc-error, HTTP502) are the only retryable class. Back off and retry; everything else is a stable answer about the name.