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

  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.