ruvnet/RuView · error
cannot bind UDP socket on {addr}: {e}
Error message
cannot bind UDP socket on {addr}: {e} What it means
Anyhow error in the calibrate subcommand: UdpSocket::bind on "{args.bind}:{args.udp_port}" returned an OS error, wrapped with the address and errno text. The socket is the CSI-frame ingestion endpoint for empty-room calibration capture, so a bind failure stops calibration before any frames are recorded. Typical causes are EADDRINUSE (another process owns the port), EACCES (privileged port without root), or EADDRNOTAVAIL (bind address not present on any interface).
Source
Thrown at v2/crates/wifi-densepose-cli/src/calibrate.rs:124
/// Execute the `calibrate` subcommand (async).
pub async fn execute(args: CalibrateArgs) -> Result<()> {
validate_args(&args)?;
let mut config = tier_config(&args.tier);
if args.min_frames > 0 {
config.min_frames = args.min_frames;
eprintln!(
"[calibrate] WARN: --min-frames={} overrides ADR-135 tier default ({} for {}). \
This relaxes the phase-concentration guarantee; do not use in production.",
args.min_frames, tier_config(&args.tier).min_frames, args.tier
);
}
let target_frames = config.min_frames as usize;
let addr = format!("{}:{}", args.bind, args.udp_port);
let socket = UdpSocket::bind(&addr).await
.map_err(|e| anyhow::anyhow!("cannot bind UDP socket on {addr}: {e}"))?;
eprintln!("[calibrate] listening on udp://{addr}");
eprintln!(
"[calibrate] capturing {} frames (~{} s, tier={}) — ensure room is empty",
target_frames, args.duration_s, args.tier
);
let mut recorder = CalibrationRecorder::new(config);
let mut buf = vec![0u8; RECV_BUF];
let mut high_z_count: u32 = 0;
let deadline = Instant::now() + Duration::from_secs(args.duration_s as u64);
loop {
let remaining = deadline.saturating_duration_since(Instant::now());
if remaining.is_zero() {
break;
}
View on GitHub (pinned to 4685618388)
Solutions
- Find and stop the process holding the port: ss -lunp | grep <port> (or lsof -i UDP:<port>), then re-run
- Or pick a free port with --udp-port and make sure the CSI sender targets the same port
- Use a bind address that exists on the host (ip addr to list) -- or the wildcard the tool documents -- rather than a stale/hardcoded IP
- Avoid ports <1024 unless running with appropriate privileges (prefer high ephemeral-range ports)
Example fix
# before ./wifi-densepose calibrate --bind 192.168.1.50 --udp-port 8500 # error: cannot bind UDP socket on 192.168.1.50:8500: Address already in use # after ss -lunp | grep 8500 # find offending pid, stop it (or it used a stale IP) ip -brief addr # confirm current host IP ./wifi-densepose calibrate --bind 192.168.1.50 --udp-port 8501 # free port, sender updated to match
Defensive patterns
Strategy: validation
Validate before calling
// preflight: probe the UDP port before launching calibration
fn udp_port_free(bind: &str, port: u16) -> bool {
std::net::UdpSocket::bind((bind, port)).is_ok()
}
if !udp_port_free(&args.bind, args.udp_port) {
anyhow::bail!("udp {bind}:{port} is busy; stop the holder or pass --udp-port");
} Try / catch
let socket = match UdpSocket::bind(&addr).await {
Ok(s) => s,
Err(e) if e.kind() == std::io::ErrorKind::AddrInUse => {
eprintln!("port {addr} busy; retrying on {fallback_port}");
UdpSocket::bind((args.bind.as_str(), fallback_port)).await?
}
Err(e) => return Err(anyhow::anyhow!("cannot bind UDP socket on {addr}: {e}")),
}; Prevention
- Check ss -lunp for the planned port before starting capture agents
- Prefer high, unprivileged ports; keep --bind set to an address that exists (verify with ip addr)
- Ensure previous calibrate/recorder processes are reaped before re-running
When it happens
Trigger: Another calibrate/recorder instance (or a previous run that did not exit) still holds the UDP port; --udp-port below 1024 used as an unprivileged user; --bind set to an IP the machine does not own (typo, VPN IP that is down); duplicate capture agents configured for the same port.
Common situations: Re-running calibration while the previous process lingers; systemd/docker port publishing conflicting with the bind; scripts using hard-coded ports that collide across services; laptops whose interface IPs change between networks making a stale --bind invalid.
Related errors
- cannot bind UDP socket on {udp_addr}: {e}
- --hap-advertise-addr is required when HAP is enabled
- calibration failed: {e}
- cannot write {output}: {e}
- cannot create output dir {}: {e}
AI-assisted analysis of ruvnet/RuView@4685618388 (2026-08-16).
Data as JSON: /api/errors/ca2731bc5f4bd38c.
Report an issue: GitHub.