Skip to content

troubleshooting

github-actions[bot] edited this page Sep 22, 2026 · 16 revisions

Troubleshooting

Symptom What to do
gcloud not installed Install the Cloud SDK only if you need Google identity. Local-only services still run
ADC unavailable /auth login or gcloud auth application-default login, then devctl auth status / /auth refresh
Wrong project Set google.project_id or check gcloud config get-value core/project. Identity shows the source
Permission denied Ask an admin for the missing IAM role; devctl doctor names the resource
Cannot impersonate SA Need roles/iam.serviceAccountTokenCreator on that service account (group binding preferred)
IAP authentication failure Confirm audience, IAP client, and that the identity matches the route. If client_id is set, the ADC refresh token must belong to that OAuth client
Port already in use Doctor lists the holder. Stop a leftover, or change config. Running your own services will also show as “in use”
Service crashes Open Logs, filter ERROR (e), restart with R
Health check failure Confirm the health URL/port; tcp is connect-only; grpc is Health/Check (SERVING); process checks only PID liveness
Proxy unavailable / missing listen port Pin proxy.listen.port (required when proxy.enabled is true — validate exits 2). Then devctl proxy start or TUI n. Starting with port 0 exits 7. Bind is loopback only
Token expired Automatic refresh uses auth.refresh_threshold_seconds; run devctl auth refresh. Open Doctor if ADC itself expired
Token audience incorrect Set auth.audience on the IAP route; Doctor flags missing audiences
IAP used a user token for an SA route Confirm the route identity is service_account; Doctor probes impersonated IAP separately
Leftover process after crash Reopen devctl — adopt when the pid is alive and the command matches ~/.devctl/state/<hash>/state.json. A start time that only drifted (sleep, WSL clock) still matches; a newer process on that pid does not. A port with no persisted pid is never attached
devctl attach fails No supervisor. Use devctl start first; attach never starts one
devctl status looks empty If the socket is down, status prints persisted state and exits 0 when nothing is running. The TUI still starts a supervisor; leftover PIDs from the previous session appear on the idle dashboard
Start exits 5 or 6 5 = spawn failed; 6 = health never passed. Doctor then Logs
start brought up extra services Empty start uses the active or first profile alphabetically — YAML key order does not matter (demo: backend, not data). A profile start no longer pulls omitted dependencies. Named devctl start invoices-api (no profile) still expands the local closure
Docker / Podman missing or daemon down A service in config declares container (the demo's postgres always does, even if you never start data). Install and start that runtime, or drop the service. Default profiles do not start postgres
Doctor offers to kill a busy port that is Docker It should not: ports owned by a running container service are healthy, and Doctor never offers to terminate the Docker or Podman daemon. Re-run Doctor after the container is up
MCP tools work but nothing starts get_status reports setup_mode: true — there is no .devctl yet. Have the agent call get_setup_guide, search_docs, and validate_config, write the files, then reload_config
devctl exec --print-env hides values Secret-like names are redacted unless you also pass --reveal (TUI: /exec <svc> --print-env --reveal or /reveal). MCP exec_service never reveals them
TUI env pane looks incomplete It now loads the same resolved map as devctl exec --print-env. If the chip says config fallback, the daemon exec call failed — check /daemon and that the supervisor is up
TUI says Configuration error but devctl config validate is clean The supervisor failed to start (often EADDRINUSE). The TUI now shows Supervisor failed to start with the bootstrap-log line. devctl daemon logs has the same text
Supervisor will not start devctl daemon logs or TUI /daemon is the bootstrap stderr, not the service log bus. unable to listen … (EADDRINUSE) means a leftover already holds that port — Doctor names the holder
TUI stale / not updating TUI follows the event bus (20–50ms batch). Quit and let a new supervisor start if an old one is still listening
status or logs_page timed out after 30000ms after sleep, and restart or quit hangs Common after a Windows sleep while devctl runs in WSL or a VS Code dev container. Quit returns without waiting on the dead connection. Start again: an unresponsive supervisor is replaced and services that are still listening are adopted
Reload needs a restart devctl reload and /reload list services whose command, env, ports, or identity changed
Configuration invalid devctl config validate — unknown fields, cycles, and missing refs fail closed. TUI v / /buffer validates before write
Config on disk is broken but the TUI still opens fine Expected: it attached to an already-running daemon and is showing its config_snapshot (last-known-good), not a fresh reparse of the broken file. Fix the file and /reload
devctl update says unavailable GitHub Releases API could not be reached. For npm: npm install --global @amr-m-abdelgawad/devctl@latest. Homebrew and GitHub binaries: see installation
MCP agent cannot connect Listener is off by default. /mcp or devctl mcp --on. URL is loopback only; snippets include the bearer token
Web UI shows {"error":"forbidden"} The page Host header was not a loopback name. Use the printed http://127.0.0.1:<port>/ (or localhost / [::1]), not a machine or Dev Container hostname. 0.8.0 required the Host port to match exactly, so WSL / Dev Container port forwarding and IPv6 localhost 403'd; upgrade to 0.8.1
devctl: command not found Run npm install --global @amr-m-abdelgawad/devctl, then ensure npm's global binary directory is on PATH. See Installation
Bundled Bun runtime was not installed Reinstall the npm package without --ignore-scripts; Bun uses its install script to select the correct platform runtime

Internal devctl logs appear in the Logs screen with source devctl.

Related

Clone this wiki locally