Troubleshooting
Run tj doctor, read its exit codes, and fix the common daemon-lock, schema, capture, and MCP issues.
Most problems surface the same way: a blank dashboard, a command that hangs, or costs that donât add up. Start with tj doctor, then work through the specific issues below.
tj doctor
tj doctor runs a battery of health checks and prints a status line for each one.
tj doctor
It checks:
- Config file: that it exists, parses as valid TOML, and has no conflicting overrides.
- DuckDB writable: that the database file can be opened. When the daemon is running it holds the write lock, so this check downgrades to âskippedâ rather than failing (thatâs the expected state after
tj onboard). - Schema vs capture: flags an agent that declares an
output_schemawhilecapture.tool_outputsis false, since validation would have no data. - Drift readiness: reports how close each agent is to its drift baseline threshold.
- Webhook security: checks alert webhook URLs and the domain allowlist.
- Span stats and staleness: surfaces an empty or stale database (no recent spans).
- Schema integrity: detects a migration recorded as applied whose column never actually landed (see schema self-heal below).
- Onboarding first signal: confirms tj has seen at least one span since setup.
Exit codes
tj doctor sets its exit code so you can gate on it in scripts:
| Code | Meaning |
|---|---|
0 | Healthy. Everything passed. |
1 | Warnings. Nothing broken, but something worth a look. |
2 | Errors. At least one check failed. |
Add --json for machine-readable output, and --repair to attempt fixes for any issue that has a known repair path.
The daemon holds the DB lock
DuckDB is single-writer. Only one process can open the database for writing at a time, and a running tj serve claims that lock. This blocks other tj commands that need write access, and can even block read-only opens.
Symptoms are a hanging command or an error mentioning a conflicting lock on ~/.tj/telemetry.duckdb.
The fix is to stop the daemon before running a command that needs direct database access:
tj stop
tj stop halts the background daemon and sweeps any stray foreground tj serve process, freeing port 7391. Restart the daemon afterward with tj serve (or let the next login start it).
Many commands avoid this entirely. When tj serve is up, commands like tj optimize and tj cost fall back to the daemonâs HTTP API instead of opening the database directly, so they keep working without a stop.
Blank Status page (schema self-heal)
A blank Status page usually means spans are being dropped on write. This happens when a database migration was recorded as applied but its ADD COLUMN never landed, so every ingest that writes the missing column fails silently.
tj doctor catches this under its Schema integrity check. Fix it with:
tj doctor --repair
The repair rebuilds the affected table. Your data is preserved. tj also re-issues the additive column definitions on every open, so the gap normally heals itself before you notice it.
Costs or content look wrong
If prompts, completions, or tool outputs arenât showing up where you expect, check your capture toggles. By default tj records only metadata (tokens, cost, latency, span structure) and stores no text.
[capture]
prompts = true
completions = true
tool_outputs = true
Flip the flag for the content you want captured, then restart tj serve to pick up the change. Captured text only ever lives on your machine. See Configuration for the full list of toggles.
MCP server wonât connect
tj mcp chooses its connection mode at startup, and each mode changes what data the tools can see:
- Proxy to the daemon. If
tj serveis reachable,tj mcpproxies to it over HTTP and sees live ingest as it happens. This is the best case. - Spawn the daemon. If no daemon is running,
tj mcptries to starttj servein the background and waits up to ten seconds for the port. - Read-only fallback. If it canât reach or start a daemon, it opens the DuckDB file directly, read-only. The read tools still work, but spans ingested after startup wonât appear until you restart.
- No config. If no config file is found, the tools return a no-config sentinel. Run
tj onboardfirst.
If your MCP tools show stale data, youâre likely in the read-only fallback. Start tj serve first, then restart the MCP client so tj mcp proxies to the live daemon.
Still stuck?
Run tj doctor --json and include the output when you file an issue. It captures the config, database, and schema state in one shot, which is usually enough to pin down the problem.