hashicorp/nomad · error

failed to identify user %v: %v

Error message

failed to identify user %v: %v

What it means

setCmdUser resolves a username/uid string to a system user via users.Lookup before exec'ing a task command. When the lookup fails (user does not exist, NSS misconfiguration, or the executor lacks permission to query the user database), it wraps the underlying error. This is the Unix path of Nomad's executor user-impersonation setup.

Source

Thrown at drivers/shared/executor/executor_unix.go:64

// necessarily kill it.
func (e *UniversalExecutor) shutdownProcess(sig os.Signal, proc *os.Process) error {
	if sig == nil {
		sig = os.Interrupt
	}

	if err := proc.Signal(sig); err != nil && err.Error() != finishedErr {
		return fmt.Errorf("executor shutdown error: %v", err)
	}

	return nil
}

// setCmdUser takes a user id as a string and looks up the user, and sets the command
// to execute as that user.
func setCmdUser(cmd *exec.Cmd, userid string) error {
	u, err := users.Lookup(userid)
	if err != nil {
		return fmt.Errorf("failed to identify user %v: %v", userid, err)
	}

	// Get the groups the user is a part of
	gidStrings, err := u.GroupIds()
	if err != nil {
		return fmt.Errorf("unable to lookup user's group membership: %v", err)
	}

	gids := make([]uint32, len(gidStrings))
	for _, gidString := range gidStrings {
		u, err := strconv.ParseUint(gidString, 10, 32)
		if err != nil {
			return fmt.Errorf("unable to convert user's group to uint32 %s: %v", gidString, err)
		}

		gids = append(gids, uint32(u))
	}

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Verify the user exists on the host: run 'id <userid>' (or 'getent passwd <userid>') as the user Nomad runs as.
  2. Fix /etc/nsswitch.conf or restart sssd/nscd if name-service lookups are failing for valid users.
  3. Ensure /etc/passwd and /etc/group exist and are readable inside the container/chroot the executor runs in.
  4. Correct the task's user field in the job spec (e.g. change 'nobodyx' to 'nobody').

Example fix

// before (job.hcl)
user = "appuser"
// after: ensure the user exists (e.g. in the image Dockerfile)
RUN useradd -r -u 1005 appuser
Defensive patterns

Strategy: validation

Validate before calling

// Go: verify the user resolves before submitting the job
if _, err := user.Lookup(taskUser); err != nil {
    return fmt.Errorf("task user %q does not resolve on this host: %w", taskUser, err)
}

Type guard

func userResolves(userid string) bool {
    _, err := user.Lookup(userid)
    return err == nil
}

Try / catch

if err := exec.SetUser(cmd, userid); err != nil {
    var uerr users.UnknownUserError
    if errors.As(err, &uerr) {
        // invalid user config: surface actionable message
    }
    return fmt.Errorf("executor set user failed: %w", err)
}

Prevention

When it happens

Trigger: Calling executor setup with a task 'user' value that does not resolve: unknown username, numeric uid absent from /etc/passwd, or a users.Lookup failure (e.g. broken NSS/SSSD, /etc/passwd unreadable in a chroot/container).

Common situations: Task stanza references a user not created in the task's image or host; running Nomad in a minimal container without /etc/passwd entries; LDAP/SSSD down so NSS lookups fail; typo'd username in job spec.

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 hashicorp/nomad@482b49bf1a (2026-09-04). Data as JSON: /api/errors/a0d2e2dbb0f63c9e. Report an issue: GitHub.