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
- Create the user before starting: `useradd -r -s /usr/sbin/nologin shadowsocks` in the image/host
- Fix the username typo in the -u flag or config file
- If using central directory (LDAP/AD), ensure NSS is configured so getpwnam resolves that user
- 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
- Create the service user in Dockerfiles/AMIs before the entrypoint runs
- Verify the user exists inside the container image (scratch/distroless images lack passwd entries)
- Prefer numeric UIDs in k8s securityContext and avoid -u in containers when the user is external
- Test the full startup path in the target environment, not just on the dev machine
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
- all plugins are exited. all connections may fail, check your
- cannot get current working directory, {err:?}
- cannot get absolute path to working directory, {err:?}
- unsupported syslog facility: {}
- `password` is required for server {svr_addr}
AI-assisted analysis of shadowsocks/shadowsocks-rust@8eb0f0a65b (2026-09-09).
Data as JSON: /api/errors/88fa4432d999eb2c.
Report an issue: GitHub.