Matched signals
- address already in use
- bind: address already in use
- listen tcp
- EADDRINUSE
- lsof
Port already in use
What this failure means
A process attempted to bind to a TCP or UDP port that is already occupied by another process on the same CI runner.
Symptoms
Faultline looks for one or more of these log fragments:
address already in use
bind: address already in use
listen tcp
EADDRINUSE
lsof
Diagnosis
A process attempted to bind to a TCP or UDP port that is already occupied by another process on the same CI runner.
Fix steps
-
Identify what is holding the port:
lsof -i :<port> ss -tlnp | grep :<port> -
Kill the occupying process:
fuser -k <port>/tcp # or: lsof -ti :<port> | xargs kill -9 -
On shared or persistent CI runners, previous jobs may leave lingering processes. Add a cleanup step at the start of the job to free known ports before starting services.
-
Parameterise the port with an environment variable so parallel CI jobs can bind to different ports without conflict.
-
Prefer ephemeral port 0 where supported: let the OS assign a free port and retrieve the assigned value from the listening socket handle.
Validation
lsof -i :<port>— confirm the port is free before starting the service.- Re-run the failing step and confirm it binds without
EADDRINUSE.
Why it matters
Shared or persistent CI runners retain processes from previous jobs. When a new job tries to bind the same port (e.g., 8080, 3000) that a lingering process is still listening on, the bind call fails immediately.
Prevention
- Use ephemeral ports in tests rather than fixed well-known ports.
- Add a cleanup step at the end of each CI job to stop background services.
- Use isolated container-per-job CI runners to avoid cross-job process leakage.
Try it locally
lsof -i :<port>
lsof -i :<port>
How Faultline detects it
Use faultline explain port-in-use to see the full playbook.
faultline analyze build.log
faultline explain port-in-use
Generated from playbooks/bundled/log/runtime/port-in-use.yaml. Do not edit directly.