shadowsocks/shadowsocks-rust · error
launch socket with name "{}" should be unique, but found {}
Error message
launch socket with name "{}" should be unique, but found {} What it means
get_launch_activate_socket expects launchd to check in exactly one file descriptor for the requested socket name. When cnt > 1 (launchd returned multiple fds for that name), it closes all of them and returns InvalidData because it cannot pick one unambiguously.
Source
Thrown at crates/shadowsocks-service/src/sys/unix/macos.rs:67
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
),
))
} else {
// Take fds[0] as the result
let fd = unsafe { *fds };
Ok(fd as RawFd)
};
if !fds.is_null() {
unsafe { libc::free(fds as *mut _) };
}
result
}View on GitHub (pinned to 8eb0f0a65b)
Solutions
- Ensure each socket in the plist has a unique Sockets key name and request that unique name
- If multiple listeners are intentional, retrieve each socket by its own distinct name instead of one shared name
- Give the requested socket its own single-entry Sockets dict in the launchd plist
Example fix
<!-- before --> <key>Sockets</key><dict><key>Listener</key><array><dict>..</dict><dict>..</dict></array></dict> <!-- after --> <key>Sockets</key><dict><key>Listener1</key><dict>..</dict><key>Listener2</key><dict>..</dict></dict>
Defensive patterns
Strategy: try-catch
Try / catch
match get_launch_activate_socket(name) {
Err(e) if e.kind() == io::ErrorKind::InvalidData && e.to_string().contains("should be unique") => {
eprintln!("plist defines multiple sockets named {name}; use unique names");
}
other => other?,
} Prevention
- Use a distinct Sockets key per listener in the launchd plist
- Avoid arrays under a single Sockets key when sockets are fetched by name
- Audit the plist with `launchctl print` after edits
When it happens
Trigger: The launchd plist declares multiple sockets under the same key name (array of listeners) or check-in returns duplicates, while the code requests a single named socket via get_launch_activate_tcp_listener/udp_socket.
Common situations: Plist Sockets entry defined as an array of several listeners under one key; copy-pasted duplicate Sockets entries with the same name; combining Bonjour + socket entries collapsing to one name.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- launch socket with name "{}" doesn't exist
- 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/fa4c03b503fe1c44.
Report an issue: GitHub.