{"record":{"id":"944a44780a2b7d0a","repo":"ruvnet/RuView","slug":"cannot-bind-addr-e","errorCode":null,"errorMessage":"cannot bind {addr}: {e}","messagePattern":"cannot bind (.+?): (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"v2/crates/wifi-densepose-cli/src/room.rs","lineNumber":149,"sourceCode":"    let (anchor, reason) = recorder.finalize(gate, now_unix());\n    let feature = if anchor.quality.accepted {\n        Some(AnchorFeature::from_series(room_id, label, &series, fs_hz))\n    } else {\n        None\n    };\n    Ok((feature, anchor, reason))\n}\n\n/// Execute `enroll`.\npub async fn enroll(args: EnrollArgs) -> Result<()> {\n    let baseline = load_baseline(&args.baseline)?;\n    let baseline_id = baseline.calibration_uuid().to_string();\n    let gate = AnchorQualityGate::default();\n\n    let addr = format!(\"{}:{}\", args.bind, args.udp_port);\n    let socket = UdpSocket::bind(&addr)\n        .await\n        .map_err(|e| anyhow::anyhow!(\"cannot bind {addr}: {e}\"))?;\n    eprintln!(\"[enroll] room='{}' baseline={} on udp://{addr}\", args.room_id, &baseline_id[..8]);\n    eprintln!(\"[enroll] follow each prompt; bad captures are re-prompted.\");\n\n    let mut session = EnrollmentSession::new(&args.room_id, &baseline_id, now_unix());\n    let mut features: Vec<AnchorFeature> = Vec::new();\n\n    for label in AnchorLabel::SEQUENCE {\n        let mut accepted = false;\n        for attempt in 1..=args.attempts {\n            let (feat, anchor, reason) =\n                capture_anchor(&socket, &baseline, &gate, label, &args.tier, args.fs_hz, &args.room_id)\n                    .await?;\n            if anchor.quality.accepted {\n                eprintln!(\n                    \"[enroll]   ✓ accepted (presence_z={:.2} motion={:.0}% frames={})\",\n                    anchor.quality.presence_z,\n                    anchor.quality.motion_rate * 100.0,\n                    anchor.quality.frames","sourceCodeStart":131,"sourceCodeEnd":167,"githubUrl":"https://github.com/ruvnet/RuView/blob/4685618388a5e49fad5b3005806f3bdd6a7c25c3/v2/crates/wifi-densepose-cli/src/room.rs#L131-L167","documentation":"enroll failed to UdpSocket::bind its CSI receive address {bind}:{udp_port}. Same failure family as the calibrate-serve ingest bind: AddrInUse when another CSI tool (calibrate-serve, room-watch, a second enroll) holds the UDP port, permission denied on ports below 1024, or an invalid --bind address.","triggerScenarios":"Running enroll while calibrate-serve or room-watch is bound to the same port (all CSI ingest tools compete for the UDP port); a privileged port as non-root; a malformed --bind value.","commonSituations":"Following the calibrate to enroll workflow without stopping the calibration server; parallel sessions on one host; the port changed on the firmware side only.","solutions":["Stop the other CSI-consuming process or give enroll its own --udp-port","Match the firmware's CSI destination port to the one enroll binds","Use a high port; avoid ports below 1024 unless privileged","Re-run enroll once the port is free — the baseline file is not affected"],"exampleFix":"// before\n$ ruview calibrate-serve &   # still bound to udp/9999\n$ ruview enroll --udp-port 9999   # cannot bind\n\n// after\n$ ruview calibrate-serve &\n$ ruview enroll --udp-port 9998   # dedicated port, firmware retargeted","handlingStrategy":"validation","validationCode":"fn udp_port_free(bind: &str, port: u16) -> bool {\n    std::net::UdpSocket::bind((bind, port)).is_ok()\n}","typeGuard":null,"tryCatchPattern":"match UdpSocket::bind(&addr).await {\n    Ok(socket) => socket,\n    Err(e) if e.kind() == std::io::ErrorKind::AddrInUse => {\n        return Err(anyhow::anyhow!(\"udp://{addr} already in use — stop calibrate-serve/room-watch or change --udp-port\"));\n    }\n    Err(e) => return Err(anyhow::anyhow!(\"cannot bind {addr}: {e}\")),\n}","preventionTips":["Run only one CSI ingest tool per port at a time; sequence calibrate, enroll, train-room with explicit handoff","Document the assigned UDP port per host","Probe the port before starting interactive enrollment so prompts never dead-air"],"tags":["rust","network","udp","bind","enrollment"],"backgroundTag":null,"analyzedSha":"4685618388a5e49fad5b3005806f3bdd6a7c25c3","analyzedAt":"2026-08-16T06:09:40.886Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}