shadowsocks/shadowsocks-rust · error

user {} not found

Error message

user {} not found

What it means

When the daemon is told to run as a different user (run_as_user / -u option), it looks up the username with libc::getpwnam. If the lookup returns NULL the user does not exist on this system, so it returns ErrorKind::InvalidInput with "user <name> not found". Privilege-dropping then fails and startup aborts.

Source

Thrown at src/sys.rs:104

    unsafe {
        let pwd = match uname.parse::<libc::uid_t>() {
            Ok(uid) => {
                let mut pwd = libc::getpwuid(uid);
                if pwd.is_null() {
                    let uname = CString::new(uname).expect("username");
                    pwd = libc::getpwnam(uname.as_ptr())
                }
                pwd
            }
            Err(..) => {
                let uname = CString::new(uname).expect("username");
                libc::getpwnam(uname.as_ptr())
            }
        };

        if pwd.is_null() {
            return Err(Error::new(ErrorKind::InvalidInput, format!("user {} not found", uname)));
        }

        let pwd = &*pwd;

        // setgid first, because we may not allowed to do it anymore after setuid
        if libc::setgid(pwd.pw_gid as libc::gid_t) != 0 {
            let err = Error::last_os_error();

            error!(
                "could not change group id to user {:?}'s gid: {}, uid: {}, error: {}",
                CStr::from_ptr(pwd.pw_name),
                pwd.pw_gid,
                pwd.pw_uid,
                err
            );
            return Err(err);
        }

View on GitHub (pinned to 8eb0f0a65b)

Solutions

  1. Create the user before starting: `useradd -r -s /usr/sbin/nologin shadowsocks` in the image/host
  2. Fix the username typo in the -u flag or config file
  3. If using central directory (LDAP/AD), ensure NSS is configured so getpwnam resolves that user
  4. Alternatively use a numeric UID where supported, or run as root without -u (not recommended)

Example fix

# before (Dockerfile)
CMD ["sslocal", "-u", "nobodyx", ...]
# after
RUN useradd -r -s /usr/sbin/nologin shadowsocks
CMD ["sslocal", "-u", "shadowsocks", ...]
Defensive patterns

Strategy: validation

Validate before calling

// Before launching with -u, verify the user resolves via getpwnam
fn user_exists(name: &str) -> bool {
    match std::ffi::CString::new(name) {
        Ok(c) => unsafe { !libc::getpwnam(c.as_ptr()).is_null() },
        Err(_) => false,
    }
}
assert!(user_exists("shadowsocks"), "user 'shadowsocks' missing — create it before starting the daemon");

Try / catch

match daemon::run_as_user("shadowsocks") {
    Err(e) if e.kind() == std::io::ErrorKind::InvalidInput && e.to_string().contains("not found") => {
        eprintln!("run-as user missing on host; aborting instead of running as root");
        std::process::exit(1);
    }
    r => r,
}

Prevention

When it happens

Trigger: Starting the daemon with -u <username> (or equivalent config) where the username has no passwd entry — typo in username, user exists only in LDAP/AD not in local passwd, or running in a minimal container (e.g. scratch/distroless) without the user defined.

Common situations: Docker containers built without `useradd`/passwd entry; systemd unit User= mismatch after image change; k8s securityContext runAsUser combined with -u name that doesn't exist inside the image; NIS/LDAP user not resolvable at startup.

Understand the failure class

Background: "User not found", "Invalid user", and "does not exist": what missing-user lookup errors mean across Rocket.Chat, LiteLLM, Phabricator, rustfs, and pnpm — this error's family across 10 libraries.

Related errors


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