{"record":{"id":"53e63342a567b00e","repo":"hashicorp/nomad","slug":"error-parsing-uid-w","errorCode":null,"errorMessage":"error parsing uid: %w","messagePattern":"error parsing uid: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"helper/users/lookup.go","lineNumber":39,"sourceCode":"//\n// Values are cached up to 1 hour, or 1 minute for failure cases.\nfunc Lookup(username string) (*user.User, error) {\n\treturn globalCache.GetUser(username)\n}\n\n// LookupUnix returns the UID, GID, and home directory for username or returns\n// an error. ID values are int to work well with Go library functions.\n//\n// Will always fail on Windows and Plan 9.\nfunc LookupUnix(username string) (int, int, string, error) {\n\tu, err := Lookup(username)\n\tif err != nil {\n\t\treturn 0, 0, \"\", fmt.Errorf(\"error looking up user %q: %w\", username, err)\n\t}\n\n\tuid, err := strconv.Atoi(u.Uid)\n\tif err != nil {\n\t\treturn 0, 0, \"\", fmt.Errorf(\"error parsing uid: %w\", err)\n\t}\n\n\tgid, err := strconv.Atoi(u.Gid)\n\tif err != nil {\n\t\treturn 0, 0, \"\", fmt.Errorf(\"error parsing gid: %w\", err)\n\t}\n\n\treturn uid, gid, u.HomeDir, nil\n}\n\n// lock is used to serialize all user lookup at the process level, because\n// some NSS implementations are not concurrency safe\nvar lock sync.Mutex\n\n// internalLookupUser username while holding a global process lock.\nfunc internalLookupUser(username string) (*user.User, error) {\n\tlock.Lock()\n\tdefer lock.Unlock()","sourceCodeStart":21,"sourceCodeEnd":57,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/helper/users/lookup.go#L21-L57","documentation":"After finding the user, LookupUnix converts the string u.Uid field to an int with strconv.Atoi; a non-numeric Uid is a corrupted or exotic user-database entry, so the conversion error is wrapped and returned.","triggerScenarios":"Calling users.LookupUnix for a user whose /etc/passwd (or NSS source) entry has a Uid field that is not a plain integer — malformed passwd line, LDAP/NSS plugin returning bad data.","commonSituations":"Hand-edited /etc/passwd with a typo in the uid column; NSS backends (LDAP, SSSD) returning malformed attributes; automated tooling writing invalid passwd entries.","solutions":["Inspect /etc/passwd for the target user and correct the uid field to a numeric value","Check the NSS/LDAP/SSSD source for malformed uidNumber attributes","Recreate the user entry with standard tooling (useradd) instead of manual edits"],"exampleFix":"// before\nnomad:x:100 :100::/home/nomad:   # malformed uid\n// after\nnomad:x:1000:1000::/home/nomad:  # valid numeric uid","handlingStrategy":"validation","validationCode":"u, err := user.Lookup(username)\nif err != nil {\n\treturn err\n}\nif _, err := strconv.Atoi(u.Uid); err != nil {\n\treturn fmt.Errorf(\"user %q has non-numeric uid %q in passwd/NSS source\", username, u.Uid)\n}\nuid, gid, home, err := users.LookupUnix(username)","typeGuard":"func hasNumericIDs(u *user.User) bool {\n\t_, uidErr := strconv.Atoi(u.Uid)\n\t_, gidErr := strconv.Atoi(u.Gid)\n\treturn uidErr == nil && gidErr == nil\n}","tryCatchPattern":"uid, gid, home, err := users.LookupUnix(username)\nif err != nil {\n\tif strings.Contains(err.Error(), \"error parsing uid\") {\n\t\treturn fmt.Errorf(\"corrupt passwd entry for %q — fix uid column: %w\", username, err)\n\t}\n\treturn err\n}","preventionTips":["Never hand-edit /etc/passwd; use useradd/usermod","Monitor NSS/LDAP sources for malformed uidNumber attributes","Validate passwd lines after automated provisioning","Fail fast at startup by looking up all configured users once"],"tags":["unix","user-lookup","parsing","passwd"],"backgroundTag":"uid-parse-error","analyzedSha":"482b49bf1aec006f089bcfc7e632d8f6ac303e5e","analyzedAt":"2026-09-04T07:54:14.808Z","contentChangedAt":"2026-09-04T07:54:14.808Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}