FortiBlox LogoFortiBlox Docs
x1id

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.

codeMeaningWhat a UI should do
unrecognizedThe 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.
ambiguousThe 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-handleRight 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-domainRight shape (dot + known TLD), but the label fails domain validation.Show a normal "not a valid domain" validation message.
not-foundThe 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-chainThe 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-errorTransport 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 statuserror messageMeaningWhat a caller should do
409ambiguous: both a handle and a domain shapeSame 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.
400invalid handle@-shaped input fails handle validation.Equivalent to the SDK's invalid-handle — treat as a validation error.
400invalid domainDomain-shaped input fails domain parsing.Equivalent to the SDK's invalid-domain.
400bad nameDomain parsed but account derivation failed.Treat as a validation error, same tier as invalid domain.
404handle not registeredWell-formed @handle, nothing registered.Equivalent to the SDK's not-found.
404domain not registeredWell-formed domain, nothing registered at that account.Equivalent to the SDK's not-found.
404account is not under the claimed TLDThe 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.
404not foundUnknown route (not a /resolve/:name, /health, or /version path).Client/integration bug — check the request path.
405method not allowedNon-GET request. The API is read-only by construction: there is no write path, no key, no mutation endpoint.Client/integration bug — use GET.
502malformed accountThe 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 ambiguous as blocking, not as a fallback chain. Don't retry the same input against "just the handle namespace" or "just the domain namespace" after seeing ambiguous — that reintroduces exactly the wrong-recipient risk the error exists to prevent.
  • not-found and no-record-for-chain are 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, HTTP 502) are the only retryable class. Back off and retry; everything else is a stable answer about the name.