shadowsocks/shadowsocks-rust · error
launch socket with name "{}" doesn't exist
Error message
launch socket with name "{}" doesn't exist What it means
On macOS launchd socket activation, get_launch_activate_socket looks up a pre-opened socket by name via launch_activate_socket. When launchd reports zero matching sockets (cnt == 0), the function returns InvalidData saying the named launch socket doesn't exist. It is raised from the process environment, not the config file.
Source
Thrown at crates/shadowsocks-service/src/sys/unix/macos.rs:55
}
Some(libc::ESRCH) => {
error!("current process is not managed by launchd, error: {}", err);
}
Some(libc::EALREADY) => {
error!(
"activate socket name \"{}\" has already been activated, error: {}",
name, err
);
}
_ => {}
}
return Err(err);
}
}
let result = if cnt == 0 {
Err(io::Error::new(
io::ErrorKind::InvalidData,
format!("launch socket with name \"{}\" doesn't exist", name),
))
} else if cnt > 1 {
for idx in 0..cnt {
unsafe {
let fd = *(fds.add(idx));
let _ = libc::close(fd);
}
}
Err(io::Error::new(
io::ErrorKind::InvalidData,
format!(
"launch socket with name \"{}\" should be unique, but found {}",
name, cnt
),
))View on GitHub (pinned to 8eb0f0a65b)
Solutions
- Start the service via launchctl with the plist containing a matching Sockets entry (launchctl load / launchctl kickstart)
- Ensure the socket name requested matches exactly the key under Sockets in the plist
- Fall back to binding the address directly when launchd check-in is unavailable (e.g. non-macOS or manual run)
Example fix
<!-- before --> <key>Sockets</key><dict><key>Listener</key>...</dict> // code requests "listener" <!-- after --> <key>Sockets</key><dict><key>listener</key>...</dict> // names match exactly
Defensive patterns
Strategy: fallback
Validate before calling
if std::env::var("LAUNCH_SOCKET_NAME").is_err() || std::env::var("launchd").is_err() {
// not under launchd check-in; bind directly
bind_manually(addr)?;
} Type guard
fn under_launchd() -> bool { std::env::var_os("launchd").is_some() } Try / catch
match get_launch_activate_socket(name) {
Err(e) if e.kind() == io::ErrorKind::InvalidData && e.to_string().contains("doesn't exist") => {
let listener = TcpListener::bind(addr).await?; // fallback to manual bind
}
other => other?,
} Prevention
- Always provide a manual-bind fallback for non-launchd environments
- Keep socket names in code and plist Sockets keys identical
- Test the daemon both via launchctl and directly
When it happens
Trigger: Running the service with a Sockets/<Name> key expected in its launchd plist but the daemon was started outside launchd, or the requested socket name doesn't match any key in the plist (LAUNCH_SOCKET_NAME / check-in mismatch).
Common situations: Running `./shadowsocks` directly from a terminal instead of via launchctl; plist Sockets dictionary renamed; typo between the code's requested name and the plist key; testing launchd activation without `launchctl load`.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- launch socket with name "{}" should be unique, but found {}
- client addr must be ipv4
- client addr must be ipv6
- not supported tcp transparent proxy type
- not supported udp transparent proxy type
AI-assisted analysis of shadowsocks/shadowsocks-rust@8eb0f0a65b (2026-09-09).
Data as JSON: /api/errors/d5bd19613b394ed4.
Report an issue: GitHub.