{"record":{"id":"ca2731bc5f4bd38c","repo":"ruvnet/RuView","slug":"cannot-bind-udp-socket-on-addr-e","errorCode":null,"errorMessage":"cannot bind UDP socket on {addr}: {e}","messagePattern":"cannot bind UDP socket on (.+?): (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"v2/crates/wifi-densepose-cli/src/calibrate.rs","lineNumber":124,"sourceCode":"\n/// Execute the `calibrate` subcommand (async).\npub async fn execute(args: CalibrateArgs) -> Result<()> {\n    validate_args(&args)?;\n\n    let mut config = tier_config(&args.tier);\n    if args.min_frames > 0 {\n        config.min_frames = args.min_frames;\n        eprintln!(\n            \"[calibrate] WARN: --min-frames={} overrides ADR-135 tier default ({} for {}). \\\n             This relaxes the phase-concentration guarantee; do not use in production.\",\n            args.min_frames, tier_config(&args.tier).min_frames, args.tier\n        );\n    }\n    let target_frames = config.min_frames as usize;\n\n    let addr = format!(\"{}:{}\", args.bind, args.udp_port);\n    let socket = UdpSocket::bind(&addr).await\n        .map_err(|e| anyhow::anyhow!(\"cannot bind UDP socket on {addr}: {e}\"))?;\n\n    eprintln!(\"[calibrate] listening on udp://{addr}\");\n    eprintln!(\n        \"[calibrate] capturing {} frames (~{} s, tier={}) — ensure room is empty\",\n        target_frames, args.duration_s, args.tier\n    );\n\n    let mut recorder = CalibrationRecorder::new(config);\n    let mut buf = vec![0u8; RECV_BUF];\n    let mut high_z_count: u32 = 0;\n    let deadline = Instant::now() + Duration::from_secs(args.duration_s as u64);\n\n    loop {\n        let remaining = deadline.saturating_duration_since(Instant::now());\n        if remaining.is_zero() {\n            break;\n        }\n","sourceCodeStart":106,"sourceCodeEnd":142,"githubUrl":"https://github.com/ruvnet/RuView/blob/4685618388a5e49fad5b3005806f3bdd6a7c25c3/v2/crates/wifi-densepose-cli/src/calibrate.rs#L106-L142","documentation":"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).","triggerScenarios":"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.","commonSituations":"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.","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)"],"exampleFix":"# before\n./wifi-densepose calibrate --bind 192.168.1.50 --udp-port 8500\n# error: cannot bind UDP socket on 192.168.1.50:8500: Address already in use\n\n# after\nss -lunp | grep 8500        # find offending pid, stop it (or it used a stale IP)\nip -brief addr              # confirm current host IP\n./wifi-densepose calibrate --bind 192.168.1.50 --udp-port 8501   # free port, sender updated to match","handlingStrategy":"validation","validationCode":"// preflight: probe the UDP port before launching calibration\nfn udp_port_free(bind: &str, port: u16) -> bool {\n    std::net::UdpSocket::bind((bind, port)).is_ok()\n}\nif !udp_port_free(&args.bind, args.udp_port) {\n    anyhow::bail!(\"udp {bind}:{port} is busy; stop the holder or pass --udp-port\");\n}","typeGuard":null,"tryCatchPattern":"let socket = match UdpSocket::bind(&addr).await {\n    Ok(s) => s,\n    Err(e) if e.kind() == std::io::ErrorKind::AddrInUse => {\n        eprintln!(\"port {addr} busy; retrying on {fallback_port}\");\n        UdpSocket::bind((args.bind.as_str(), fallback_port)).await?\n    }\n    Err(e) => return Err(anyhow::anyhow!(\"cannot bind UDP socket on {addr}: {e}\")),\n};","preventionTips":["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"],"tags":["rust","udp","sockets","calibration","networking","port-in-use"],"backgroundTag":null,"analyzedSha":"4685618388a5e49fad5b3005806f3bdd6a7c25c3","analyzedAt":"2026-08-16T06:09:40.886Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}