ruvnet/RuView · error
cannot bind HTTP listener on {http_addr}: {e}
Error message
cannot bind HTTP listener on {http_addr}: {e} What it means
tokio TcpListener::bind failed for the HTTP API address {http_bind}:{http_port} in calibrate-serve. io::Error causes: AddrInUse (another HTTP service or a second calibrate-serve on that port), permission denied on privileged ports, or a --http-bind address the host does not own. This is a startup failure, distinct from runtime serve errors.
Source
Thrown at v2/crates/wifi-densepose-cli/src/calibrate_api.rs:363
let state = ApiState { cmd_tx, status, window, fs_hz: 15.0, enroll };
let mut app = build_router(state);
// Optional bearer auth — required before any non-loopback exposure.
if let Some(token) = args.token.clone() {
app = app.layer(axum::middleware::from_fn_with_state(token, require_bearer));
eprintln!("[calibrate-serve] bearer auth ENABLED");
} else if args.http_bind != "127.0.0.1" && args.http_bind != "localhost" {
eprintln!(
"[calibrate-serve] WARNING: bound to {} with NO --token — anyone on the network can drive calibration",
args.http_bind
);
}
let http_addr = format!("{}:{}", args.http_bind, args.http_port);
let listener = tokio::net::TcpListener::bind(&http_addr)
.await
.map_err(|e| anyhow::anyhow!("cannot bind HTTP listener on {http_addr}: {e}"))?;
eprintln!("[calibrate-serve] HTTP API on http://{http_addr} (GET / for the route list)");
axum::serve(listener, app)
.await
.map_err(|e| anyhow::anyhow!("HTTP server error: {e}"))?;
Ok(())
}
// ---------------------------------------------------------------------------
// Ingest task — owns the UDP socket and the optional active recorder
// ---------------------------------------------------------------------------
struct ActiveSession {
recorder: CalibrationRecorder,
room_id: String,
tier: String,
started: Instant,
deadline: Instant,View on GitHub (pinned to 4685618388)
Solutions
- Stop the occupying process or choose a different --http-port (ss -tlnp to find it)
- Use a port of 1024 or higher, or grant CAP_NET_BIND_SERVICE for low ports
- Set --http-bind to an address that exists on the host (127.0.0.1 for local, the NIC IP for LAN)
- When binding non-loopback, pass --token — the code warns that an unauthenticated LAN-bound API lets anyone drive calibration
Example fix
// before $ ruview calibrate-serve --http-bind 0.0.0.0 --http-port 80 # permission denied / AddrInUse // after $ ruview calibrate-serve --http-bind 0.0.0.0 --http-port 8080 --token <secret>
Defensive patterns
Strategy: validation
Validate before calling
fn tcp_port_free(bind: &str, port: u16) -> bool {
std::net::TcpListener::bind((bind, port)).is_ok()
} Try / catch
match tokio::net::TcpListener::bind(&http_addr).await {
Ok(listener) => listener,
Err(e) if e.kind() == std::io::ErrorKind::AddrInUse => {
return Err(anyhow::anyhow!("http://{http_addr} already in use — stop the other service or change --http-port"));
}
Err(e) => return Err(anyhow::anyhow!("cannot bind HTTP listener on {http_addr}: {e}")),
} Prevention
- Allocate dedicated ports for the calibration API in deployment config
- Treat repeated bind failures in health checks as a port-conflict incident, not a crash-loop bug
- Never bind non-loopback without --token — the CLI itself warns the API would be drivable by anyone on the network
When it happens
Trigger: Another web service already listening on the chosen port; --http-port below 1024 as non-root; --http-bind set to an address not present on the host.
Common situations: Collisions with dev servers on common ports like 8080; container port maps where the host port is taken; typo'd bind address; running two calibration API instances on one host.
Related errors
- cannot bind UDP socket on {udp_addr}: {e}
- cannot bind {addr}: {e}
- Non-JSON response from {method} {path} (status {resp.status}
- HTTP server error: {e}
- Request failed
AI-assisted analysis of ruvnet/RuView@4685618388 (2026-08-16).
Data as JSON: /api/errors/5d6417a1d9416b8b.
Report an issue: GitHub.