Troubleshooting
Calling
401 with a key that looks right
Check which header your SDK sends. The Anthropic SDK sends only x-api-key;
OpenAI-shaped clients send Authorization: Bearer. Both are accepted, but a
truncated paste is not. The key is sk-aile- plus exactly 48 hex characters.
A bare Bearer with nothing after it is not accepted as a key.
404 on every request
Almost always the base URL. OpenAI clients want the /v1 suffix because they
append /chat/completions to it. The Anthropic SDK and Claude Code append
/v1/messages themselves, so they take the bare origin. A doubled /v1/v1/ is
served as /v1/, so …/v1 works for them too.
| SDK | Base URL |
|---|---|
| OpenAI | https://api.aile.sh/v1 |
| Anthropic | https://api.aile.sh |
400 naming provider ids
The model's prefix is not a provider Aile knows. There is no cross-provider
fallback by design. Use an id from GET /v1/models. See
Model names.
400 saying the model names no provider
The model has no provider prefix. Send <provider>/<model> (e.g.
cc/claude-sonnet-5, or local/<model> for self-hosted), or keep the bare name
and add x-aile-provider. A key pinned to one provider also works with bare names.
To let any provider serve it, write auto/ instead of a provider
(auto/claude-sonnet-5), or send x-aile-provider: any.
Claude Code and the Codex CLI are the exception: with no pin or header, a bare
name from Claude Code goes to claude and one from Codex goes to codex. See
Agents.
400 saying the request names no model
The body has no model, or is not a JSON object at all: malformed JSON, an empty
body, null or an array all read this way. Check what your client actually sent.
400 saying a pin and the model name different providers
A key pin, a route or x-aile-provider names one provider and the model's prefix
names another. Where the pinned provider's own ids carry no prefix (claude,
codex), another provider's route such as codex/gpt-5.6-sol cannot be its model, so
the request is refused before anything is dialled. Do what the message says: drop
the header, use a key not limited to that provider, or name one of its models.
404 saying a provider does not serve this path
The provider you named cannot speak the endpoint you posted to, or the path is
not one Aile serves (/v1/completions). Nothing was held or charged. Use
/v1/chat/completions, /v1/messages or /v1/responses, or a provider that
speaks the one you need.
404 saying the model has no published list price
Aile only serves models with a published price. Pick another model from
GET /v1/models. A 503 asking you to retry means the price list could not be
read just then.
503 naming a provider
Nobody is sharing that provider right now. This is availability rather than an outage:
GET /v1/models reflects who can serve this minute. Retry after a delay, widen
your filters, or drop the provider pin.
By the time you see it, several sharers were already tried. Keep your own retry loop short and backed off.
503 with an x-aile-status header
Cloudflare replaces an origin 502 or 504 with its own page, so /v1 sends
both as 503 and puts the real code in x-aile-status. The body is still
Aile's.
502: the sharers tried failed. On the image, audio, video and other non-chat endpoints, "upstream X answered HTTP N; you were not charged" is the sharer's account failing, not your request.504saying to send"stream": true: a non-streaming request ran past the deployment's time limit. Stream it instead.
403 saying you cannot be paid for serving yourself
Every sharer left for that model is you, or an account that looks like the same party. Other sharers are always tried first, so this means none of them could serve. Retry later, or pick another provider.
500 saying "An unexpected error occurred (request …)"
Something failed on Aile's side. Retry; if it repeats, report the request id in
the message, which matches the response's x-request-id. A self-hosted sharer's
failure reads "Self-hosted capacity failed (request …)" as a 502.
The stream arrives all at once
With curl, pass -N; curl buffers its own output otherwise. Through a proxy of
your own, make sure it honours x-accel-buffering: no.
A 429 that will not clear
Honour retry-after when it is present. A shared upstream limit is jittered on
our side so sibling accounts do not all return in lockstep, but a provider's own
stated reset time is never shortened.
The answer looks short
Check for a terminal error frame. A mid-stream failure arrives as an SSE frame, not an HTTP status, so code that accumulates deltas without inspecting frames reads a failure as a short answer. See Errors.
A stream can also simply stop: the provider closed it cleanly before its own end event, usually an account at the edge of its quota. Retry. On the Anthropic and Responses wires that account cools for ten minutes, so the retry goes to another sharer.
A stream with no answer after 25 s is committed to 200 early and carries
x-aile-edge-hold and only the x-aile-* headers that could no longer change (not the sharer or price, except on self-hosted capacity — see Headers), so a failure after
that is always a frame. A held image or music request that does not stream
fails as a 200 whose JSON body is the error.
The bill is higher than expected
The reservation is taken against the max_tokens your request authorises rather
than the reply you got. The difference is refunded, but that ceiling is the lever.
A key's balance is billed up to the cap sent upstream, which tools, thinking, an unset max_tokens or a route that sends no cap (codex) can put above the quote.
A reported cache write bills at its own rate (up to 2x input), and a stream you
abort after the model has started reasoning or calling a tool still bills its
prompt. Price it first with aile price <model> --max-tokens N.
Sharing
fetch failed at aile login
Usually a stale serverUrl from an old install. Known-dead addresses are retired
automatically, but you can set it explicitly:
1aile config serverUrl https://api.aile.sh
An account shows unverified
That is the identity signal rather than the liveness signal.
- An API key can never be attested: nothing signs a key exchange. This is expected.
- A subscription showing
unprovenhas not attested yet. Re-link it withaile connect <provider>.
aile check-key refreshes the live signal. It cannot change identity. See
Verification.
An API key is refused at link, or the key check says refused-on-serve
At link, the provider's own key check turned the key down, so nothing was stored. Check the key and link it again; an OpenRouter management key or an expired one is refused the same way.
refused-on-serve means the provider refused the key on a real request. A
passing key check cannot lift that: link a new key. See
Connect an account.
A model is not on the market
A model is listed only after it passes a test on your account. aile models <n>
shows each one as listed, untested, failed, can't sell or off, with the reason;
aile test <n> runs the test (one small request on your own quota). A test does
not expire, but linking a different credential on the account resets it. Untested
models still serve callers who name them, after every tested sharer.
A Codex model that your ChatGPT plan does not carry fails the test with "not on this account's Codex model list"; that is the plan, not the key.
aile usage says "no quota reported"
That is normal: most providers publish no quota. It does not mean the account is out of
capacity. Use aile capacity to see what each kind can serve.
aile nodeless <n> on is refused
The account is a subscription, and the CLI turns nodeless on for API-key accounts only. The relay accepts it for any linked account: the web dashboard (Dashboard → Sharing → Providers, Route set to Direct) turns it on for a subscription, which then serves from Aile's egress rather than your node. See Nodeless for what that risks.
aile start says "Already running (pid N)"
One node per machine. Stop the other process, or inspect it with aile status,
which reads the lock file and can report a node running in another terminal.
Self-hosted model shows "not serving"
The endpoint is enabled but unreachable, usually a wrong port. aile capacity
prints the reason.
1aile local http://127.0.0.1:11434 # fix the URL2aile config localModels llama3 # name the models if /v1/models is empty
Advertise exactly what your endpoint answers to. Callers send it as
local/<model>; Aile strips the prefix before forwarding.
A price was refused
The bounds live on the server. aile rates prints the allowed range, and the
server's refusal names the limit you crossed. A margin runs from 0 (free) to 1
(list price). Dollar prices are retired, and a model with no list price is not
sold at any margin.
Wallet balance reads "could not be read just now"
The Solana RPC was unreachable. It is not $0: reporting zero when the read
failed is the one answer that line refuses to give. Try again shortly.
Nothing is routing to me
Sharer selection is price-first. A cheaper sharer is tried before you no matter how fast you are, and pricing yourself out is quiet: there is no error, and requests go elsewhere.
1aile sharers --model <m>
That is the marketplace as callers see it, priced and in routing order. If you are not near the top, that is why.
The node runs but restarts oddly under systemd
Turn off the client's own reconnect and let the supervisor own the policy:
1aile config autoReconnect false
With both enabled the process retries internally and never exits, so
Restart=always never fires and the restart counter never advances.
Still stuck
aile statusandaile capacityanswer most "is it working" questions.- Add
--jsonto any read command for exact values. aile config --pathprints where settings live.- The API reference runs requests against the live relay, which is the quickest way to separate a client problem from a service one.