facebook/flow · error · std::io::Error
socket path has no basename
Error message
socket path has no basename
What it means
with_addr runs a Unix-socket operation by chdir-ing into the socket's parent directory and binding/connecting to ./basename; this keeps the sockaddr path short (Unix addr length limits) and prevents the relative sockaddr from escaping the callback. It requires the socket path to have a final component: paths whose Path::file_name() is None — "/", "..", or anything ending in a parent component — are rejected up front with ErrorKind::InvalidInput before any socket work happens.
Source
Thrown at rust_port/crates/flow_common_socket/src/socket.rs:51
#[cfg(unix)]
Unix(String),
}
// On Linux/Mac/BSD, sockaddr_un.sun_path is a fixed length. To handle longer paths,
// we chdir to that directory and use a relative path instead. The callback provides
// a Unix.sockaddr with a relative path that you can use to bind or read from. Perform
// as little as possible within the callback, since it has an unexpected working dir.
// This function tries to make it awkward for the Unix.sockaddr with the relative path
// to escape from the callback.
#[cfg(unix)]
pub fn with_addr<T>(addr: &Addr, f: impl FnOnce(&SockAddr) -> io::Result<T>) -> io::Result<T> {
let cwd = std::env::current_dir()?;
match addr {
Addr::Unix(file) => {
let path = Path::new(file);
let dir = path.parent().unwrap_or_else(|| Path::new("."));
let base = path.file_name().ok_or_else(|| {
io::Error::new(io::ErrorKind::InvalidInput, "socket path has no basename")
})?;
std::env::set_current_dir(dir)?;
let mut guard = CwdGuard(Some(cwd));
let sockaddr = SockAddr::unix(Path::new(".").join(base))?;
let result = f(&sockaddr);
guard.restore()?;
result
}
}
}
// Initializes the unix domain socket
fn unix_socket(sock_name: &str) -> io::Result<SocketListener> {
flow_common::sys_utils::with_umask(0o111, || {
let dir = Path::new(sock_name)
.parent()
.filter(|dir| !dir.as_os_str().is_empty())
.unwrap_or_else(|| Path::new("."));View on GitHub (pinned to f88ac94bcf)
Solutions
- Pass a concrete socket file path with a real basename, e.g. /tmp/flow-standalone.sock.
- Validate the configured socket path before startup: path.file_name() must be Some and non-empty.
- Log the final resolved socket path at startup so a misjoined path is visible immediately.
Example fix
// before: joining a dir with nothing yields a path with no basename
let sock = dir.join(""); // dir == "../run" -> file_name() == None -> "socket path has no basename"
// after: always append an explicit socket file name
let sock = dir.join("flow.sock");
assert!(sock.file_name().is_some()); Defensive patterns
Strategy: validation
Validate before calling
use std::path::Path;
fn has_socket_basename(p: &Path) -> bool {
p.file_name().map(|f| !f.is_empty()).unwrap_or(false)
}
// call before constructing Addr::Unix / calling with_addr
assert!(has_socket_basename(Path::new(&sock_path))); Type guard
fn is_no_basename_error(e: &std::io::Error) -> bool {
e.kind() == std::io::ErrorKind::InvalidInput && e.to_string().contains("no basename")
} Try / catch
Fail fast on InvalidInput 'no basename': include the offending path in the error you surface. This is a configuration bug, not a transient condition — retrying will not help.
Prevention
- Always build socket paths as dir.join("name.sock") with a literal basename.
- Assert file_name().is_some() on any socket path coming from config before startup.
- Log the final socket path at server startup.
When it happens
Trigger: Constructing Addr::Unix from a path like Path::new("/"), "..", or "foo/../.." (file_name() returns None for all of these) and passing it to with_addr, which SocketStream/UnixListener bind and connect paths go through.
Common situations: Socket path assembled by joining config values that collapse to ".." or that end with a separator (e.g. format!("{dir}/") with no filename appended); empty socket-dir config; a templated path whose filename variable is unset.
Related errors
- lock file is already held
- invalid line
- invalid column
- failed to write cli errors
- failed to flush cli errors
AI-assisted analysis of facebook/flow@f88ac94bcf (2026-08-20).
Data as JSON: /api/errors/8537c786e0cbad1e.
Report an issue: GitHub.