hashicorp/nomad · error

Couldn't change owner/group of %v to (uid: %v, gid: %v): %w

Error message

Couldn't change owner/group of %v to (uid: %v, gid: %v): %w

What it means

The final step of dropDirPermissions is os.Chown(path, uid, gid) to hand the shared directory to the resolved 'nobody' uid/gid. This error wraps the chown failure with the target uid/gid for diagnosis. Even with root privileges, the kernel can refuse the change due to filesystem restrictions or invalid ids.

Source

Thrown at client/allocdir/fs_unix.go:62

	}

	u, err := users.Lookup("nobody")
	if err != nil {
		return fmt.Errorf("Unable to find nobody user: %w", err)
	}

	uid, err := getUid(u)
	if err != nil {
		return err
	}

	gid, err := getGid(u)
	if err != nil {
		return err
	}

	if err := os.Chown(path, uid, gid); err != nil {
		return fmt.Errorf("Couldn't change owner/group of %v to (uid: %v, gid: %v): %w", path, uid, gid, err)
	}

	return nil
}

// getUid for a user
func getUid(u *user.User) (int, error) {
	uid, err := strconv.Atoi(u.Uid)
	if err != nil {
		return 0, fmt.Errorf("Unable to convert Uid to an int: %w", err)
	}

	return uid, nil
}

// getGid for a user
func getGid(u *user.User) (int, error) {
	gid, err := strconv.Atoi(u.Gid)

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Check the wrapped error for EPERM/EINVAL and inspect the alloc-dir mount type and options (mount | grep alloc).
  2. Avoid root-squashed NFS for data_dir, or adjust the export's anonuid/anongid settings.
  3. Verify the resolved nobody uid/gid (getent passwd nobody) are valid on this filesystem.
  4. Clear immutable attributes (chattr -i) if lsattr shows them on the directory.

Example fix

// before: alloc dir on root-squashed NFS
/data/nomad  *(rw,sync,root_squash)
// after: allow root ownership changes
/data/nomad  *(rw,sync,no_root_squash)
Defensive patterns

Strategy: try-catch

Validate before calling

// verify chown works on the alloc-dir filesystem before allocations
probe := filepath.Join(allocDir, ".chown-probe")
os.WriteFile(probe, nil, 0o600)
err := os.Chown(probe, nobodyUID, nobodyGID)
os.Remove(probe) // err must be nil

Try / catch

if err := td.Build(); err != nil {
    if strings.Contains(err.Error(), "Couldn't change owner/group") {
        var errno syscall.Errno
        if errors.As(err, &errno) && errno == syscall.EPERM {
            log.Printf("alloc-dir FS rejects chown; check NFS root_squash / mount opts")
        }
    }
    return err
}

Prevention

When it happens

Trigger: os.Chown(path, uid, gid) failed after 'nobody' was successfully resolved, during chroot-isolation setup of the shared alloc directory.

Common situations: Alloc dir on root-squashed NFS (root mapped to anonymous, chown denied); filesystem mounted with 'nosuid'/read-only or an FS that disallows chown; uid/gid out of range for the filesystem; immutable/append-only attributes.

Related errors


AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04). Data as JSON: /api/errors/dc991d221870d721. Report an issue: GitHub.