Troubleshooting
Symptoms you are likely to hit, and what each one actually means.
A service is stuck on "starting"
A yellow starting state means Kranz is waiting for evidence, not that something is broken. Focus the service and press 2 to see what it waits for.
Waiting for a dependency. Details shows which one. The dependency's readiness must pass before this service starts. Check the dependency's own readiness probe — if the probe is wrong, the gate never opens.
Waiting for its own readiness. The process started, but the probe has not passed yet. Common causes:
- the probe URL points at a port the service does not actually use;
- the service binds
localhostonly, while the probe uses a different host; initial_delayis shorter than the real startup time and the failures have not yet accumulated tofailure_threshold.
To see whether the probe or the service is at fault, run the probe by hand:
curl -v http://127.0.0.1:3001/readyIf that works while Kranz still waits, the probe configuration and the real endpoint disagree — compare them in Details.
A port is already taken
Kranz checks declared ports before starting and names the owner rather than failing obscurely. The dialog distinguishes a process Kranz manages from an external one, and terminating an external process always requires your explicit confirmation.
If the port belongs to a leftover process from a previous session, stop it from the dialog. If it belongs to something you want to keep, change the service's port or start the other tool instead.
A service shows "unknown"
unknown only applies to detached resources, and it means the status probe could not tell Kranz what the resource is doing. It is a deliberate "no evidence" state, not a failure.
Causes, in order of likelihood:
The probe host is unreachable. An SSH probe against a sleeping laptop cannot answer. Kranz shows
unknowninstead of claimingstopped.The probe timed out. Raise
timeout; a remote probe often needs more than the default2s.The probe returned an unclassified exit code. This happens only if you declared
stopped_exit_codes— a code in neither set is unclassified by design. Check the code your script actually returns:bashssh host ./stack-status.sh; echo "exit: $?"
The service's log pane records the reason as [Kranz] Status unavailable: …. An unknown resource is polled on the slower stopped_interval, so recovery can take up to 30 seconds by default.
A service did not start and mentions a prerequisite
A before_start entry failed, so Kranz did not start the service against an unprepared environment. The logs name the action and what happened:
[Kranz] Prerequisite failed: action "migrate" · exited with code 1Run that action on its own — expand the service with Enter, select the action, press s — and read its output. Prerequisites with run: once are remembered only after they succeed, so fixing the cause and starting again retries it.
Detached logs are empty
A detached resource has no process for Kranz to read output from. It shows logs only when you provide lifecycle.logs, and only while it is running:
lifecycle:
logs:
command: docker compose logs -f --tail=100The command must stream and stay attached. A command that prints once and exits produces one burst of output and then nothing.
Mouse clicks stop working
Some integrated terminals silently reset mouse reporting when focus moves. Kranz re-enables tracking periodically and when the window regains focus, so clicking again usually recovers within a second. Keyboard control is never affected, and every mouse action has a key binding — see controls.
Colors look wrong or unreadable
Kranz derives its palette from the terminal background by default. If your terminal reports its background inaccurately, pin the mode explicitly:
ui:
color_mode: dark # or light
background: theme # stop deriving from the terminalCtrl+T opens the live picker to try values before saving them. See appearance.
Configuration changes have no effect
Kranz watches the selected configuration and referenced dotenv files. The TUI shows when they change; press Ctrl+L to apply a valid change. A CLI or MCP client can request a reload explicitly. Running services with changed settings keep their accepted snapshot until they are restarted.
- The change was invalid. The previous configuration keeps running and the error is reported. Fix the error and save again.
- The file is not one Kranz loaded. A conventional root file wins in its own directory; otherwise recursive discovery builds a virtual project. Run
kranz config sources(or pressmin the dashboard) to see every loaded file as an include tree. A missing branch is usually a glob that matched elsewhere, a discovery root ormax_depththat is too narrow, or aninclude_depth_truncateddiagnostic inkranz config check. - The value comes from an override layer or protected policy. Run
kranz config sources --by-serviceto see which files overrode the service, thenkranz config explain SERVICEfor the ordered field provenance. - A partial file passed with
-fadds services instead of changing them.-fcomposes complete projects; pass partial files with--override. - An override layer seems ignored. A file's own
overrides:list patches only that file's services by their original names (api). To change a service another file contributes, pass--overrideand use its display name (catalog/api).
If a reload removes a running service, choose whether to stop it or keep it running outside the configured list. A service that cannot be stopped leaves the accepted configuration in place and produces an error.
An environment variable is not what I expect
Precedence runs from lowest to highest:
.envbeside the configuration file that declares the servicedefaults.envdefaults.env_files, in order- service
env_files, in order - service
env
A variable already exported in your shell wins over the adjacent .env, but never over an explicit configuration value. Details shows the resolved environment file list for the selected service.
Leaving the TUI leaves something running
First check which exit action you chose. Detach closes only the TUI, so the complete runtime and all of its services remain available to CLI, MCP, and a later TUI. Confirmed shutdown ends the runtime, but detached resources default to stop_on_exit: false, so shared external infrastructure is not torn down merely because the runtime ended. The quit dialog lists both parts of this contract before you choose.
Set stop_on_exit: true if runtime shutdown should also run the external stop command. Process-supervised services always stop with their runtime; they cannot be left behind after shutdown.
A restart policy is being ignored
availability.restart applies to process-supervised services only. Kranz does not restart a detached resource it does not own — the configuration is rejected rather than silently ignored.
Also check max_restarts: once the limit is reached the service stays stopped until you start it again.
Still stuck
Open the lifecycle playground, which simulates managed, observe-only, healthy, unhealthy, and unknown resources locally with marker files. Reproducing a symptom there separates a Kranz problem from a configuration problem in your own project.
If it is a Kranz problem, please open an issue with your configuration and the version from kranz --version.