shadowsocks/shadowsocks-rust · error

launch socket with name

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.

Solutions

  1. Start the service via launchctl with the plist containing a matching Sockets entry (launchctl load / launchctl kickstart)
  2. Ensure the socket name requested matches exactly the key under Sockets in the plist
  3. 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

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


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

Appendix: 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)