{"record":{"id":"06b4ceae38e125b7","repo":"block/buzz","slug":"failed-to-bind-uds-uds-path-e","errorCode":null,"errorMessage":"Failed to bind UDS {uds_path}: {e}","messagePattern":"Failed to bind UDS (.+?): (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/buzz-relay/src/main.rs","lineNumber":1350,"sourceCode":"        .map_err(|e| anyhow::anyhow!(\"Failed to bind {}: {e}\", config.bind_addr))?;\n    info!(addr = %config.bind_addr, \"buzz-relay TCP listening\");\n\n    #[cfg(unix)]\n    if let Some(ref uds_path) = config.uds_path {\n        use std::os::unix::fs::FileTypeExt as _;\n        match std::fs::symlink_metadata(uds_path) {\n            Ok(meta) if meta.file_type().is_socket() => {\n                let _ = std::fs::remove_file(uds_path);\n            }\n            Ok(_) => {\n                return Err(anyhow::anyhow!(\n                    \"BUZZ_UDS_PATH {uds_path} exists but is not a socket\"\n                ));\n            }\n            Err(_) => {}\n        }\n        let uds_listener = tokio::net::UnixListener::bind(uds_path)\n            .map_err(|e| anyhow::anyhow!(\"Failed to bind UDS {uds_path}: {e}\"))?;\n        info!(path = %uds_path, \"buzz-relay UDS listening\");\n\n        let router_uds = router.clone();\n        let mut uds_rx = shutdown_tx.subscribe();\n        let uds_handle = tokio::spawn(async move {\n            axum::serve(uds_listener, router_uds.into_make_service())\n                .with_graceful_shutdown(async move {\n                    uds_rx.changed().await.ok();\n                })\n                .await\n                .ok();\n        });\n\n        let mut tcp_rx = shutdown_tx.subscribe();\n        axum::serve(\n            tcp_listener,\n            router.into_make_service_with_connect_info::<std::net::SocketAddr>(),\n        )","sourceCodeStart":1332,"sourceCodeEnd":1368,"githubUrl":"https://github.com/block/buzz/blob/f956e6fe06a76e50cbd8fba1a162482e752e7f1a/crates/buzz-relay/src/main.rs#L1332-L1368","documentation":"After the stale-socket cleanup, serve() calls tokio::net::UnixListener::bind(BUZZ_UDS_PATH) and wraps the io::Error. At this point the path is known to be free, so failures come from the environment: parent directory missing (NotFound), no write permission on the directory (PermissionDenied, common when running non-root without a writable /run), the path exceeding the kernel's ~107-byte sun_path limit (InvalidInput on Linux), or a filesystem that does not support unix sockets.","triggerScenarios":"BUZZ_UDS_PATH=/run/buzz/relay.sock when /run/buzz does not exist; relay user lacking write access to /run or /var/run; deeply nested container paths (long overlayfs/kubelet pod paths) blowing past sun_path; socket placed on an NFS or otherwise socket-hostile mount; readonly-root filesystem with no writable socket dir.","commonSituations":"Containers running as non-root without tmpfs at /run; missing mkdir -p in entrypoints; distroless images with no pre-created runtime dirs; socket paths under /var/lib/kubelet/pods/... in hostPath mounts.","solutions":["Create the parent directory: mkdir -p /run/buzz (entrypoint or Dockerfile) and rerun.","Fix ownership/permissions so the relay user can write there (chown/chmod), or use a writable path like /tmp.","Shorten the path — keep the full absolute path well under ~104 characters.","Move the socket to a local or tmpfs filesystem if the current mount does not support sockets."],"exampleFix":"# before: Error: Failed to bind UDS /run/buzz/relay.sock: No such file or directory (os error 2)\n\n# after: create the dir in the image/entrypoint\nRUN mkdir -p /run/buzz && chown relay:relay /run/buzz","handlingStrategy":"validation","validationCode":"// Pre-flight: the parent dir must exist and the path must fit sun_path (~104 bytes on Linux).\nfn uds_bindable(path: &str) -> bool {\n    let p = std::path::Path::new(path);\n    match p.parent() {\n        Some(dir) => dir.is_dir() && path.len() < 104,\n        None => false,\n    }\n}\n\nif let Some(uds) = std::env::var(\"BUZZ_UDS_PATH\").ok() {\n    assert!(uds_bindable(&uds), \"{uds} not bindable — mkdir -p the parent, check perms, shorten the path\");\n}","typeGuard":"fn classify_uds_bind_error(e: &std::io::Error) -> &'static str {\n    match e.kind() {\n        std::io::ErrorKind::NotFound => \"parent directory missing\",\n        std::io::ErrorKind::PermissionDenied => \"no write permission on directory\",\n        std::io::ErrorKind::InvalidInput => \"path too long for sun_path\",\n        _ => \"filesystem may not support unix sockets\",\n    }\n}","tryCatchPattern":"let uds_listener = match tokio::net::UnixListener::bind(uds_path) {\n    Ok(l) => l,\n    Err(e) if e.kind() == std::io::ErrorKind::NotFound => {\n        return Err(anyhow!(\"parent dir missing for {uds_path}: mkdir -p it first\"))\n    }\n    Err(e) => return Err(anyhow!(\"Failed to bind UDS {uds_path}: {e}\")),\n};","preventionTips":["Entrypoints: mkdir -p the socket directory (and chown it to the relay user) before exec","Keep UDS paths short and on tmpfs (/run) in containers","For readonly-root images, mount an emptyDir/tmpfs at the socket directory"],"tags":["rust","unix","unix-domain-socket","filesystem","permissions","startup"],"backgroundTag":"unix-socket-bind-failed","analyzedSha":"f956e6fe06a76e50cbd8fba1a162482e752e7f1a","analyzedAt":"2026-08-16T22:11:40.750Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}