Troubleshooting
AI — Troubleshooting
The most common failures, and the one-line fix. On the WebSocket these arrive as an
assistant:error event { code, message, retryAfter? }; over REST they're HTTP status
codes. See also Common errors.
401 / AUTH_MISSING · AUTH_INVALID
Your JWT is missing, malformed, or expired. Re-authenticate and resend with
Authorization: Bearer <jwt>. On the WebSocket, pass the token in the handshake
(auth.token, query.token, or the Authorization header) — a missing token emits
AUTH_MISSING and a bad one AUTH_INVALID, then the socket disconnects.
429 / RATE_LIMIT
You hit the per-admin AI rate limit. Back off and retry after retryAfter seconds
(the event and the 429 body both carry it). This is a short-window limiter, not a hard
cap.
429 / TOKEN_BUDGET_EXCEEDED
The workspace's monthly AI token budget is spent — the message mentions "budget" and it resets next month. This is distinct from the rate limit: raise the plan or wait for the reset. AI credits are billed per run by real provider cost, so heavy tool use burns the budget faster.
503 — "No AI providers are configured"
No provider API key is set, so the factory registered zero providers. Set at least one
of OPENAI_API_KEY, ANTHROPIC_API_KEY, GEMINI_API_KEY, or KIMI_API_KEY. The
default provider is AI_DEFAULT_PROVIDER (default openai); if that key is absent the
factory falls over to any other configured provider, so configuring one is enough.
The answer streams but a change never happens
Writes do not auto-run — the assistant pauses and emits assistant:confirm_action
(v1) / assistant:confirmation_required (v2). Nothing is written until the user
approves. If your UI ignores that event, the change silently never happens. Render the
approve/decline card and echo the actionId (v1) / approvedCallIds (v2) back.
"This action is no longer pending" on confirm
The confirm re-resolves the original proposal from conversation history and refuses
anything that isn't still pending — a stale actionId, a replayed confirm, or edited
tool args. Ask the assistant to propose the action again, and confirm with the
actionId from the latest assistant:confirm_action. A duplicate confirm of a
completed action is safely replayed ("already completed"), not re-executed.
"Tool X is not available in this mode"
The confirmed tool isn't in the conversation's mode whitelist (e.g. a schema/email tool
attempted from the WhatsApp channel, which excludes web-only tools). Use the tool from a
mode/channel that exposes it, or send with the correct mode.
403 / plan limit on a write
The tool ran but a plan/usage limit blocked it (PlanLimitExceededException). This is a
billing gate, not an auth one — upgrade the plan or reduce usage. Row-level access is
still enforced too: the assistant only ever sees and edits records the caller's
A/G/M/D level allows (see Authorization).
v2 routes return 404
The assistant is gated by AI_V2_ENABLED (and the builder/onboarding flows by their
own flags). With the flag off, every /ai-v2/* route and the /ai-v2/chat socket
return 404 — that's your feature-detection signal. Enable the flag to turn the
assistant on.
Next
- Recommended patterns → Best Practices
- The design → Architecture