pbakaus/impeccable · error
Error: listen EADDRINUSE: {}
Error message
Error: listen EADDRINUSE: {}
What it means
The tiny_http server failed to bind 127.0.0.1 on the requested port. The command reports it as a Node-style `listen EADDRINUSE` error and exits 1. EADDRINUSE means the address/port is already in use by another socket.
Source
Thrown at crates/context/src/serve_question.rs:417
return 1;
}
},
None => io.stdin().to_string(),
};
let detached_key = if a.has("detached-serve") { a.arg("key") } else { None };
let state = Arc::new(Mutex::new(ServerState::new(cwd.clone(), qdir.clone(), detached_key.clone(), idle_grace_ms)));
{
let mut st = state.lock().unwrap();
if let Err(msg) = st.load_round(&raw) {
io.err(&format!("serve-question: {}\n", msg));
return 1;
}
}
let port = if port_arg.is_finite() && port_arg >= 0.0 { port_arg as u16 } else { 0 };
let server = match tiny_http::Server::http(("127.0.0.1", port)) {
Ok(s) => s,
Err(e) => {
io.err(&format!("Error: listen EADDRINUSE: {}\n", e));
return 1;
}
};
let actual_port = server.server_addr().to_ip().map(|a| a.port()).unwrap_or(port);
let url = format!("http://127.0.0.1:{}/", actual_port);
if a.has("detached-serve") {
let _ = std::fs::create_dir_all(&qdir);
let key = a.arg("key").unwrap_or_default();
let st = json!({ "pid": std::process::id(), "port": actual_port, "url": url });
let _ = std::fs::write(state_file(&qdir, &key), json_compact(&st));
} else {
io.out(&format!("QUESTION URL: {}\n", url));
io.out("Waiting for the user to choose in the browser (Ctrl-C aborts)...\n");
}
if !a.has("no-open") {
open_system_browser(&url, &env);
}
let _ = io.stdout.flush();View on GitHub (pinned to 2bc2879276)
Solutions
- Kill the existing process holding the port (`lsof -iTCP:<port> -sTCP:LISTEN`).
- Omit the --port flag or pass 0 to let the OS pick a free ephemeral port.
- Choose a different explicit port.
- If a detached serve is still alive, reuse its URL rather than serving again.
Example fix
// before impeccable serve-question --port 3000 detached-serve payload.json // after impeccable serve-question payload.json // port 0, OS-assigned
Defensive patterns
Strategy: fallback
Validate before calling
const net = require('net');
function portFree(port) {
return new Promise(res => {
const s = net.createServer();
s.once('error', () => res(false));
s.listen(port, '127.0.0.1', () => s.close(() => res(true)));
});
} Try / catch
try {
run(`impeccable serve-question --port ${port} ...`);
} catch (e) {
if (e.stderr.includes('EADDRINUSE')) return run(`impeccable serve-question ...`); // omit --port
throw e;
} Prevention
- Omit --port so the OS assigns an ephemeral port.
- Before detached-serve, check for a still-running previous instance.
- Use `lsof -iTCP:<port> -sTCP:LISTEN` to find squatters.
- In containers, ensure the loopback port is not mapped twice.
When it happens
Trigger: `serve-question --port <n>` (or a detached-serve key invocation with an explicit port) where an explicit finite port >= 0 is requested and another process already listens on it. Port 0 (ephemeral) cannot produce this.
Common situations: A previous serve-question instance still running (especially detached-serve), another dev server on the same port, or a lingering TIME_WAIT/locked port in containers.
Related errors
- serve-question: server failed to start{}
- serve-question: log at {}. A sandboxed exec that cannot list
- Live server not running. Start one with: {cmd}
- Download failed: {e}
- concept-seed: --candidate-count must be an integer from 5 to
AI-assisted analysis of pbakaus/impeccable@2bc2879276 (2026-09-08).
Data as JSON: /api/errors/87027a93fc44487e.
Report an issue: GitHub.