{"record":{"id":"e5951ae5ab60e5f4","repo":"hashicorp/nomad","slug":"unable-to-convert-user-s-group-to-uint32-s-v","errorCode":null,"errorMessage":"unable to convert user's group to uint32 %s: %v","messagePattern":"unable to convert user's group to uint32 (.+?): (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"drivers/shared/executor/executor_unix.go","lineNumber":77,"sourceCode":"// setCmdUser takes a user id as a string and looks up the user, and sets the command\n// to execute as that user.\nfunc setCmdUser(cmd *exec.Cmd, userid string) error {\n\tu, err := users.Lookup(userid)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to identify user %v: %v\", userid, err)\n\t}\n\n\t// Get the groups the user is a part of\n\tgidStrings, err := u.GroupIds()\n\tif err != nil {\n\t\treturn fmt.Errorf(\"unable to lookup user's group membership: %v\", err)\n\t}\n\n\tgids := make([]uint32, len(gidStrings))\n\tfor _, gidString := range gidStrings {\n\t\tu, err := strconv.ParseUint(gidString, 10, 32)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"unable to convert user's group to uint32 %s: %v\", gidString, err)\n\t\t}\n\n\t\tgids = append(gids, uint32(u))\n\t}\n\n\t// Convert the uid and gid\n\tuid, err := strconv.ParseUint(u.Uid, 10, 32)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"unable to convert userid to uint32: %w\", err)\n\t}\n\tgid, err := strconv.ParseUint(u.Gid, 10, 32)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"unable to convert groupid to uint32: %s\", err)\n\t}\n\n\t// Set the command to run as that user and group.\n\tif cmd.SysProcAttr == nil {\n\t\tcmd.SysProcAttr = &syscall.SysProcAttr{}","sourceCodeStart":59,"sourceCodeEnd":95,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/drivers/shared/executor/executor_unix.go#L59-L95","documentation":"Each group id string returned by u.GroupIds() is parsed with strconv.ParseUint(gid, 10, 32) to build the uint32 list used in the syscall credential. If a GID string is non-numeric or exceeds 32 bits, the loop returns this wrapped parse error.","triggerScenarios":"GroupIds() returns a malformed or out-of-range GID (e.g. negative or >4294967295 value coming from an NSS/LDAP backend, or non-numeric garbage in the group database).","commonSituations":"LDAP directory exposing SIDs or non-numeric group identifiers; corrupted /etc/group entries; 64-bit GIDs on unusual NSS sources.","solutions":["Run 'id <username>' and inspect each returned group for non-numeric or >4294967295 values.","Fix the offending /etc/group entry or the LDAP/NSS source producing invalid GIDs.","Remove the user from groups with invalid GIDs until the source is corrected."],"exampleFix":"// before (/etc/group)\nbroken-group:x:4294967296:appuser\n// after\nbroken-group:x:4294967295:appuser","handlingStrategy":"validation","validationCode":"// Go: sanity-check that every gid for the task user parses as uint32\nfor _, g := range gidStrings {\n    if _, err := strconv.ParseUint(g, 10, 32); err != nil {\n        return fmt.Errorf(\"invalid gid %q for task user\", g)\n    }\n}","typeGuard":"func isUint32(s string) bool {\n    _, err := strconv.ParseUint(s, 10, 32)\n    return err == nil\n}","tryCatchPattern":"if err := exec.SetUser(cmd, userid); err != nil {\n    if strings.Contains(err.Error(), \"convert user's group to uint32\") {\n        // group data corrupt: fail fast, don't retry\n    }\n    return err\n}","preventionTips":["Validate GIDs in the directory are numeric and < 4294967296.","Audit /etc/group for malformed entries during provisioning.","Test 'id <user>' output on LDAP-joined hosts before production."],"tags":["unix","gid","strconv","nomad-executor"],"backgroundTag":"invalid-numeric-id","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"}