{"record":{"id":"69be4a2b710eb0a8","repo":"ruvnet/RuView","slug":"cannot-bind-udp-socket-on-udp-addr-e","errorCode":null,"errorMessage":"cannot bind UDP socket on {udp_addr}: {e}","messagePattern":"cannot bind UDP socket on (.+?): (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"v2/crates/wifi-densepose-cli/src/calibrate_api.rs","lineNumber":320,"sourceCode":"        .route(\"/api/v1/calibration/baselines\", get(baselines))\n        .route(\"/api/v1/room/state\", get(room_state))\n        .route(\"/api/v1/room/train\", post(train_room))\n        .route(\"/api/v1/enroll/anchor\", post(enroll_anchor))\n        .route(\"/api/v1/enroll/geometry\", post(enroll_geometry))\n        .route(\"/api/v1/enroll/status\", get(enroll_status))\n        .layer(CorsLayer::permissive())\n        .with_state(state)\n}\n\n/// Run the calibration HTTP API server (blocks until Ctrl-C).\npub async fn execute(args: CalibrateServeArgs) -> Result<()> {\n    std::fs::create_dir_all(&args.output_dir)\n        .map_err(|e| anyhow::anyhow!(\"cannot create output dir {}: {e}\", args.output_dir))?;\n\n    let udp_addr = format!(\"{}:{}\", args.udp_bind, args.udp_port);\n    let socket = UdpSocket::bind(&udp_addr)\n        .await\n        .map_err(|e| anyhow::anyhow!(\"cannot bind UDP socket on {udp_addr}: {e}\"))?;\n    eprintln!(\"[calibrate-serve] CSI ingest on udp://{udp_addr}\");\n\n    let status = Arc::new(RwLock::new(SharedStatus {\n        udp_port: args.udp_port,\n        default_tier: args.tier.clone(),\n        output_dir: args.output_dir.clone(),\n        ..Default::default()\n    }));\n\n    let (cmd_tx, cmd_rx) = mpsc::channel::<CalCommand>(8);\n    let window = Arc::new(RwLock::new(VecDeque::<f32>::with_capacity(LIVE_WINDOW)));\n    let enroll = Arc::new(RwLock::new(HashMap::<String, RoomEnroll>::new()));\n\n    // Background ingest task owns the socket + recorder.\n    {\n        let status = status.clone();\n        let default_tier = args.tier.clone();\n        let output_dir = args.output_dir.clone();","sourceCodeStart":302,"sourceCodeEnd":338,"githubUrl":"https://github.com/ruvnet/RuView/blob/4685618388a5e49fad5b3005806f3bdd6a7c25c3/v2/crates/wifi-densepose-cli/src/calibrate_api.rs#L302-L338","documentation":"tokio UdpSocket::bind failed for the CSI ingest address {udp_bind}:{udp_port} at calibrate-serve startup. The io::Error is typically AddrInUse (another process already bound that UDP port, e.g. a previous calibrate-serve, enroll, or room-watch instance), permission denied for privileged ports below 1024, or an invalid/unassignable --udp-bind address.","triggerScenarios":"Starting calibrate-serve while another calibrate-serve/enroll/room-watch still holds the same UDP port; --udp-port below 1024 as non-root; passing a --udp-bind literal that cannot be parsed or is not assigned to the host.","commonSituations":"A previous server instance was never stopped (orphaned process, missing systemd stop); two CSI tools configured to the same default port; containers without CAP_NET_BIND_SERVICE trying low ports.","solutions":["Free the port: stop the other process (ss -ulpn / lsof -i udp/<port>) or pick a different --udp-port","Use a UDP port of 1024 or higher, or grant the capability when a low port is required","Pass a numeric, bindable address in --udp-bind (127.0.0.1, 0.0.0.0, or a NIC IP)","After changing the port, align the ESP32 firmware's CSI destination port with it"],"exampleFix":"// before\n$ ruview calibrate-serve --udp-port 9999   # cannot bind: AddrInUse (old instance)\n\n// after\n$ ss -ulpn | grep 9999\n$ kill <old-pid>\n$ ruview calibrate-serve --udp-port 9999","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(&udp_addr).await {\n    Ok(socket) => socket,\n    Err(e) if e.kind() == std::io::ErrorKind::AddrInUse => {\n        return Err(anyhow::anyhow!(\"udp://{udp_addr} already in use — stop the other CSI tool or change --udp-port\"));\n    }\n    Err(e) => return Err(anyhow::anyhow!(\"cannot bind UDP socket on {udp_addr}: {e}\")),\n}","preventionTips":["Run one CSI ingest service per UDP port per host; use a process manager that stops old instances first","Prefer unprivileged high ports for CSI ingest","Bind 127.0.0.1 unless remote nodes must stream in, and pair non-loopback HTTP binds with --token"],"tags":["rust","network","udp","bind","calibration"],"backgroundTag":null,"analyzedSha":"4685618388a5e49fad5b3005806f3bdd6a7c25c3","analyzedAt":"2026-08-16T06:09:40.886Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}