quavon doctor ​
./deploy/compose/quavon doctor # table
./deploy/compose/quavon doctor --json # {"ok": bool, "findings": [{check, status, code, message, fix?}]}doctor runs inside the application image with the configuration of the api service (plus the migrator URL). It runs every check, each with its own timeout, so one broken dependency does not hide the other results. Each finding has a status (ok, warn, fail), a stable code, a message and, for problems, a fix. Secrets, passwords, URLs with credentials and tokens are never printed.
Exit code: 0 when there is no fail (warnings are allowed), 1 otherwise or on invalid arguments.
Codes appear with status ok when the check passed. The tables list what a warn or fail means and how to fix it.
General ​
| Code | Status | Cause | Fix |
|---|---|---|---|
| QD001 | fail | A check did not finish within its timeout (15 s; 60 s for the encryption scan). | Make sure the dependency of that check is reachable from the containers; run doctor again. |
| QD002 | fail | A check failed unexpectedly. The message names the error type and code only. | Run doctor again; inspect quavon logs <service>. Report persistent failures. |
| QD003 | warn | A check was skipped because something it needs failed (invalid configuration, unusable system database, uninitialized schema). | Fix the failures reported above it and run doctor again. |
Configuration ​
| Code | Status | Cause | Fix |
|---|---|---|---|
| QD101 | fail | The configuration of api, worker or migrate is invalid. The message is the same report the service prints at start-up: every variable with its problem, the expected format and an example. | Correct the variables in .env, the Compose file or the secret files and restart the stack. |
Database ​
Checked separately for the app, system and migrator roles (database:<role>), using DATABASE_SSL as configured.
| Code | Status | Cause | Fix |
|---|---|---|---|
| QD201 | fail | PostgreSQL is not reachable (connection refused, DNS failure, timeout). | Check quavon status and quavon logs postgres; check host and port in the URL. |
| QD202 | fail | PostgreSQL rejected the role's credentials. | The secret file and the role password differ. Restore the original secret from backup, or correct the admin URL and re-run the init service. |
| QD203 | fail | TLS negotiation failed: DATABASE_SSL does not match the server, or the server certificate is not trusted. | Use DATABASE_SSL=disable for the bundled postgres. For external servers use require, or verify-full with DATABASE_SSL_CA_FILE. |
| QD204 | fail | Another connection error, for example the database does not exist. The message contains the PostgreSQL error code. | Check the database name and the PostgreSQL log. |
| QD205 | fail | Migrations shipped with this version are not applied. | Run the init service (docker compose -p quavon up init in deploy/compose), then restart api and worker. |
| QD206 | fail | The schema is not initialized (no migration table or no access to it). | Same as QD205. Dependent checks are skipped (QD003). |
| QD207 | warn | pgvector is not installed, so semantic code search is unavailable. Lexical code search still works. | Only needed for the hybrid code index mode. Use a PostgreSQL server that offers the vector extension (the bundled image does) and run the init service again. See code-index.md. |
Valkey ​
| Code | Status | Cause | Fix |
|---|---|---|---|
| QD301 | fail | Valkey does not answer PING (not running, wrong host, or VALKEY_TLS does not match the server). | Check quavon status, quavon logs valkey, the host in VALKEY_URL; use rediss:// and VALKEY_TLS=true only with TLS. |
| QD302 | fail | Valkey rejected the password. | secrets/valkey_url must contain the password from secrets/valkey_password; restart the stack. |
Encryption keys ​
Every stored encrypted value (GitHub App credentials, LLM keys, session tokens, provider credentials) is decrypted with the configured keys.
| Code | Status | Cause | Fix |
|---|---|---|---|
| QD401 | ok | All values are readable and on the current key. | – |
| QD402 | warn | Some values are still encrypted with a previous key (or the legacy format). The message counts them per table. | Run quavon keys rotate, confirm with quavon keys status, then remove the old key (operations.md). |
| QD403 | fail | Some values cannot be decrypted with any configured key. | Add the key that encrypted them to QUAVON_PREVIOUS_ENCRYPTION_KEYS (from your secrets backup), or re-enter the affected secrets in the admin UI. |
Public URL ​
| Code | Status | Cause | Fix |
|---|---|---|---|
| QD501 | fail / warn | PUBLIC_URL is not https (fail in production, warning otherwise). | Use https; re-run the installer with --domain and a TLS mode. |
| QD502 | warn | PUBLIC_URL/healthz is not reachable from inside the stack (DNS, firewall, certificate not ready or not trusted). | Check DNS and quavon logs caddy. Expected with TLS_MODE=internal, and while ACME is still issuing the certificate. |
GitHub ​
| Code | Status | Cause | Fix |
|---|---|---|---|
| QD601 | warn | No GitHub App is registered. | Complete setup with the link from quavon setup-token. |
| QD602 | fail | The GitHub host of an app is not reachable. | Allow outbound HTTPS from the containers to GitHub (DNS, firewall, proxy). |
| QD603 | fail | GitHub rejected the app's JWT (wrong app ID, revoked private key, app deleted, or a skewed clock). | Check the app on GitHub; register it again via setup if the key was revoked; fix the clock (QD701). |
| QD604 | fail | The stored app credentials cannot be decrypted. | Restore the encryption key used when the app was registered (QD403) or register the app again. |
| QD605 | ok | Reminder: <PUBLIC_URL>/auth/github/callback must be a callback URL of each GitHub App, otherwise sign-in fails. | Add it in the app settings on GitHub if sign-in fails with a redirect error. |
| QD606 | ok | Reminder: each GitHub App must deliver webhooks to <PUBLIC_URL>/webhooks/github. | Correct the webhook URL in the app settings if events do not arrive. |
Clock ​
| Code | Status | Cause | Fix |
|---|---|---|---|
| QD701 | warn / fail | The clock differs from GitHub's Date header by more than 30 s (warn) or 120 s (fail). GitHub rejects app JWTs from skewed clocks. | Enable time synchronisation on the host, for example timedatectl set-ntp true. |
| QD702 | warn | The time could not be read from the GitHub API. | Allow outbound HTTPS to GitHub; verify NTP on the host. |
Outbox ​
| Code | Status | Cause | Fix |
|---|---|---|---|
| QD801 | warn | The oldest due outbox job has been waiting longer than 300 s. | Check that worker is running and can reach Valkey (quavon status, quavon logs worker). |
Instance admin ​
| Code | Status | Cause | Fix |
|---|---|---|---|
| QD901 | warn | No user is instance admin yet. | Complete setup with the link from quavon setup-token, or use quavon break-glass. |
Sandbox ​
Checked from the runner health records in Valkey. --sandbox (set by the wrapper when the sandbox profile is enabled) expects a runner; --sandbox-smoke asks every runner for a fresh escape smoke test and waits up to three minutes. Setup: sandbox.md.
| Code | Status | Cause | Fix |
|---|---|---|---|
| QD951 | fail | A runner is expected but none reports health. ok shows the effective backend, runtime and platform. | Start sandbox-runner (COMPOSE_PROFILES=sandbox) and check quavon logs sandbox-runner. |
| QD952 | fail (production) / warn | The runner uses docker-runc-insecure. | Install gVisor, register runsc and set QUAVON_SANDBOX_BACKEND=docker-runsc. |
| QD953 | fail | firecracker is configured but /dev/kvm is missing. | Use Firecracker only on KVM hosts; use docker-runsc elsewhere. |
| QD954 | fail | The runner refuses jobs because its backend is unhealthy. | Fix the listed problems, for example a missing runsc runtime or a platform mismatch. |
| QD955 | fail | Enterprise edition: the runner shares a host with the API and worker. | Move the runner to a dedicated node. |
| QD956 | warn | Sandbox image classes are missing on the runner. | Run deploy/images/sandbox/build.sh and restart the runner. |
| QD957 | fail / warn | The escape smoke test failed (fail), has not run or is older than 24 h (warn). | Stop using the runner on failure; otherwise run quavon doctor --sandbox-smoke. |
| QD958 | fail | A requested smoke test did not finish in time. | Check quavon logs sandbox-runner. |