Documentation menu
Troubleshooting
Diagnose missing sockets, withheld process metadata, permission errors, and scoped-kill refusals.
Start with the exact message or symptom below. Most cases come from socket state, operating-system permissions, or a safety check refusing an uncertain target.
A port shows in another tool but not in Kickoutchi
list and the TUI show listening TCP sockets and bound UDP sockets • the socket states that
occupy a local port. Established and transitional connections are deliberately not in that view, so
a port you see in a connection-oriented tool may not be a listener. Kickoutchi also uses
native collectors rather than parsing ss, netstat, or lsof, so output can differ from those
tools by design.
The full native state is collected • it just isn’t in the legacy view.
kick list --snapshot-json and
kick watch both retain every native TCP state, including established,
time_wait, and the transitional ones.
Process metadata is missing (shows -)
The socket is visible but some process metadata wasn’t readable • usually because the process belongs to another user. The row still appears, tagged with partial permission so the blank is explained rather than hidden. Re-run with higher privileges to fill it in.
Permission denied when killing
You don’t have the rights to signal that process (exit 4). On Linux/macOS, try sudo; on Windows,
use an elevated terminal. If a --port target has no readable owning PID, Kickoutchi reports
permission denied rather than guessing.
A protected process asks for stronger confirmation
That’s protection working. Type the PID or the process name to confirm. If a process is
protected that you’d rather treat normally, adjust your
protected_processes • but the built-in safety names are there
for good reasons.
kill --port says the target is ambiguous
Two or more PIDs own that port, so Kickoutchi refuses to guess. It prints the candidates; re-run
with --pid and the one you mean.
why says the port is free, but my server still can’t bind
Three usual causes, and why distinguishes them if you read the per-endpoint rows:
- Different address.
why 3000defaults to127.0.0.1and::1. Your server may be binding0.0.0.0or a LAN address. Re-run with--all-addressesor an explicit--address. - Different protocol. The default is TCP. Add
--udpor--all-protocols. - A race. A successful probe binds and immediately closes. It proves the endpoint was free at that instant; it does not reserve it. Something else can take it a millisecond later.
why exits 4 for a low port
Ports below 1024 usually need elevation to bind, so the probe is refused before it can learn
anything. permission_denied is reported honestly rather than being turned into “free” or “busy” •
current bindability is genuinely unknown. Re-run with elevation if you need a real answer.
watch printed collection_gap
A poll failed. Kickoutchi keeps the last valid snapshot rather than discarding it, so the failure
can’t manufacture a wave of false release events, and it retries. If three consecutive polls fail,
watch flushes the third gap and exits 1. Gaps ignore your endpoint filters on purpose • you
always find out that you stopped seeing.
watch shows filter=indeterminate
Your filter needed a fact Kickoutchi couldn’t read • usually an owner PID or a process name behind a permission boundary. Rather than silently dropping the event, it’s emitted and marked indeterminate, so you know a filter might have hidden something. Definite non-matches are still suppressed.
watch missed a port that definitely opened
watch polls; it is not a kernel event feed. A socket that opens and closes between two polls is
never observed, and several changes can collapse into one net difference. Lower --interval (down
to 100ms) to narrow the window • you cannot close it.
My label isn’t showing up
- The CLI and TUI only show a
LABELcolumn when at least one label is configured. The TUI also needs a wide enough terminal. Structured output always carries the label. - Selectors are exact:
protocol,address, andportall have to match, and TCP and UDP are separate. Useaddress = "*"for a protocol-and-port wildcard. - An exact selector always wins over a wildcard for the same endpoint.
- Hostnames, CIDR ranges, interface names, and
%zonesyntax are rejected • usescope_idfor an IPv6 scope.
See Endpoint labels for the validation rules.
Docker-owned port details are partial or unavailable
Docker context is enrichment, shown when the Docker CLI is available • it’s never required for normal port listing. Without the Docker CLI, you’ll still see the port and process, just not the container mapping.
Kickoutchi also disables PATH-resolved Docker enrichment while running as root, set-ID, with Linux
capabilities, or from an elevated Windows token. This prevents a writable docker executable on
PATH from crossing a privilege boundary. Run Kickoutchi without elevation when you specifically
need optional container metadata; elevate only when OS process permissions require it.
Linux: kernel too old for pidfd termination
Listing ports works on older kernels, but safe pidfd-based termination needs Linux 5.3+. On a
newer kernel, the signal is tied to a process handle so a recycled PID can’t be hit by mistake.
Windows: some processes need an elevated terminal
Higher-privilege processes can hide metadata or reject termination from a normal shell. Re-open your terminal as administrator and try again.
macOS: process identity changed before termination
macOS has no pidfd, so Kickoutchi re-checks the process identity right before signalling. If the PID was reused by a different process between your confirmation and the signal, it refuses and sends nothing. Re-list and try again.
Linux/macOS tree/group kill says it thawed everything
That means the scoped kill hit a safety refusal after freezing began: permission denied, identity
drift, protected descendant, incomplete metadata, cap overflow, or a sweep that would not converge.
Kickoutchi sent SIGCONT to every member it had stopped and sent no termination signal.
If a cleanup error names PIDs, those are processes whose SIGCONT was refused and which may
still be stopped • check them. A member that exited during the freeze is not reported, because
there is nothing left to resume.
Windows tree kill reports incomplete metadata or partial containment
Windows tree kill has no SIGSTOP equivalent. It preflights before the Job Object commit and fails
closed if missing creation-time metadata could hide a descendant. After commit it freezes the job
for a final validation sweep, and if a live member can’t join the job it withholds termination
entirely rather than terminating that one process individually • doing so would reopen the
descendant-spawn window it just closed. Delivered, already-exited, unconfirmed, and not-terminated
PIDs are all reported separately instead of collapsing into “success”.
Windows: --group or TUI t/T is unavailable
That’s expected. Windows supports read-only inspect and CLI --tree, but --group is a POSIX
process-group feature and the Windows TUI still omits the tree keys. If inspect or CLI --tree is
unknown on Windows, run kick --version and update to the latest release.
The TUI says “Terminal too small”
The table needs at least 80×20. Resize the window (or zoom out your terminal font) and the UI comes back.
kickoutchi-update is missing
The updater shipped with the installer starting at a certain release. If you installed earlier,
rerun the latest installer once to opt in • future upgrades can then use kickoutchi-update.