Skip to content

Troubleshooting

The order of troubleshooting: look at tansr doctor (CLI) or the error code (other forms) first, then find the fix in the tables below; nine times out of ten you will not need to contact anyone.

终端窗口
tansr doctor # 人读报告
tansr doctor --json # 机器可读

Zero model calls, zero network, zero subprocesses; exit code 0 = usable, 1 = there is a blocking problem. /doctor inside the TUI is the same report. It shows the facts from the most recent assembly fetch — after changing configuration in the console, run the CLI once to refresh.

Section What healthy looks like What to do when it is not Blocking?
node_version ≥ 22.19 Upgrade Node, or switch to the single-file executable (bundles its own runtime) Yes
config_sources Each of the five layers loaded / absent, none skipped skipped = that layer has a JSONC syntax error or a non-object root; fix or delete the file Yes
config_diagnostics 0 entries, or info level only Each entry names layer / key path / expected type; invalid values have been dropped and fall back to a lower layer error level is blocking
model_resolution alias → provider / model “Unknown model alias or ref”: check modelAliases and providers.models; “Missing API key: environment variable X is not set”: export that variable Yes
context_window / context_scheme Both window values and the clamp side; scheme production Unknown window → declare maxContext for the model; a non-production scheme is only a warning No
custom_commands / mcp_connections None skipped; a lazy server not yet connected still counts as healthy For a failed MCP server look at its error code; /mcp reconnect No
terminal / workspace_trust / output_style TTY and size; trusted; the style exists Untrusted = read-only sandbox, /trust grant; a non-existent style name is reported honestly No
localProviders (attribution) Platform mode: local providers pruned, as expected; escape hatch: a banner For “no provider configured”, look here first to tell “not configured” from “pruned” No
Credential storage (attribution) OS keychain If it fell back to a plaintext file, check the directory permissions; rerun tansr init No
Model selection attribution The model.selected value and the layer that provided it; suppressed state When the project layer pins modelAliases.main, the user layer’s sticky choice is suppressed — expected No
Plan “Personal (CLI only, no plan fee)” or “tier · expiry · state” The Personal tier is not a fault; for grace / fallen-back states renew in the console No
Media tools Four facets, each byo / platform / none All none comes with enablement guidance: the three variables for your own endpoint, or ask the administrator to enable a media pool No
Unattended baseline auto with signs of isolation Without such signs a prominent notice; once you have confirmed isolation, suppress with TANSR_ISOLATED=1 No
Session storage / memory Session count, bytes, artifact directories, corrupted directories Read-only, deletes nothing on your behalf; clean up with tansr sessions prune No
Symptom Fix
“The TUI needs an interactive terminal (TTY)” You started tansr inside a pipe; use -p for non-interactive runs
“Missing API token: pass –token or set TANSR_SERVE_TOKEN” tansr serve fails closed and will not start an unauthenticated service
“Server failed to start” / “Invalid value for –port” The port is in use or invalid
“Session does not exist” / “Cannot resume session” The --resume id is wrong or the directory is in use; run tansr --resume without an argument to pick from a list
Exit code 5 pointing to tansr init An unattended form was started before initializing; sign in first, or set TANSR_ESCAPE_LOCAL=1 for local mode
Exit code 3 A limit was reached: --max-turns / budget / tool rounds; raise it or split the task
Exit code 4 The prompt is too long and compaction is unavailable; switch to a model with a larger window
“Concurrency has reached the plan limit” banner Only new sessions are rejected; send again after 30 seconds or upgrade the plan

The authoritative table of every code is Error codes; here are only the ten you hit most often, with the first thing to do.

Code HTTP Where you see it First fix
unauthorized 401 Token expired or revoked; the session service’s authenticate returned null CLI: sign in again with tansr init. SDK: go back to your backend and mint a new token. Mobile: fix the login state, then reconnect explicitly. This is the only code that means the token is bad
token_expired 401 The login token expired Sign in again / refresh
invalid_api_key 401 The PAT is invalid Recreate the PAT in the console, tansr init --fresh
rate_limited 429 Platform rate limiting, or the session-service host’s rate limit / plan quota (detail.scope: 'plan') Wait the whole number of seconds in Retry-After, then retry; do not resend more densely
plan_concurrency_exceeded 429 The plan’s concurrency hard cap Only new sessions are rejected; send again by hand after 30 seconds; consider upgrading
insufficient_balance 402 Balance exhausted Top up; retrying does not help
model_not_authorized 403 The model is not in the app’s authorized set Grant the app that model in the console
validation_failed 400 The request payload has an invalid shape Read message and fix the request; it is not a network problem
payload_too_large 413 A body cap was exceeded (e.g. raw voice audio > 24 MiB) Split or compress; not retryable
session_archived 410 The platform session was archived (30 days inactive) Create a new session; this one cannot be continued

A few more that are frequent but self-explanatory: upstream_error (502, upstream model failure, back off and retry), upstream_timeout (504, same), quota_exceeded (429, daily quota), forbidden (403, a capability flag is off or ownership does not match), context_window_exceeded (400, compact first).

SDK (Node / Electron): tell assembly time from run time. At assembly time read TansrSdkError.code (invalid_options: fix the code; assembly_failed: look at cause; capability_disabled: enable the flag in the console); at run time look at turn.error.recoverable in the event stream — true is advisory, only false is a failure. An event stream that “hangs” is almost always a missing session.close(); “every tool is denied” is almost always a missing permission.askUser. Details in Errors and retries.

Session service (@tansr/serve): look at GET /readyz first (a 503 carries reasons); then at the structured log entries request.completed / store.commit_failed / session.rejected, correlated by the x-request-id response header. resume always returning 409 resume_unavailable = no store wired; 500 store_corrupted is common with a shared storage directory (an unsafe configuration); on session creation, 503 upstream_unavailable means token minting on the platform side is unavailable, 503 overloaded is this host’s admission cap, and 503 draining means a graceful shutdown is in progress.

Mobile (Android / iOS): look at connectionState first. Retrying is the normal L1 reconnect; Recovering is the L2 rebuild; AuthExpired → Failed(Unauthorized) means the token was refreshed 2 times and is still 401 — fix the login state, then call start() explicitly. 401 as soon as it connects usually means the headers from authProvider are not accepted by the server’s authenticate; an emulator that cannot connect usually means Android used 127.0.0.1 instead of 10.0.2.2.

  • The output of tansr doctor --json (it contains no key values; credentials appear as fingerprints).
  • The error code and the full message; for the session service, also the x-request-id.
  • Steps to reproduce and the time; for billing issues, the order number or billing month.
  • If convenient, the transcript from tansr sessions export <id> (keys are redacted automatically).

Entry points are in Contact support.