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

  1. Ensure each socket in the plist has a unique Sockets key name and request that unique name
  2. If multiple listeners are intentional, retrieve each socket by its own distinct name instead of one shared name
  3. 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

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


AI-assisted analysis of shadowsocks/shadowsocks-rust@8eb0f0a65b (2026-09-09). Data as JSON: /api/errors/fa4c03b503fe1c44. Report an issue: GitHub.