hashicorp/nomad · error

cgroupslib: unable to update reserve cpuset with %q: %w

Error message

cgroupslib: unable to update reserve cpuset with %q: %w

What it means

partition.write() also persists the reserved cores into nomad.slice/reserve/cpuset.cpus after updating the share set. This error wraps an os.WriteFile failure on the reserve cpuset file, so kernel state no longer matches Nomad's in-memory core partition (possible drift between share and reserve writes).

Source

Thrown at client/lib/cgroupslib/partition_linux.go:117

	p.lock.Lock()
	defer p.lock.Unlock()

	p.reserve.RemoveSet(cores)

	// Use the intersection with the usable cores to avoid removing more cores than available.
	p.share.InsertSet(p.usableCores.Intersect(cores))
	return p.write()
}

func (p *partition) write() error {
	shareStr := p.share.String()
	if err := os.WriteFile(p.sharePath, []byte(shareStr), 0644); err != nil {
		return fmt.Errorf("cgroupslib: unable to update share cpuset with %q: %w", shareStr, err)
	}

	reserveStr := p.reserve.String()
	if err := os.WriteFile(p.reservePath, []byte(reserveStr), 0644); err != nil {
		return fmt.Errorf("cgroupslib: unable to update reserve cpuset with %q: %w", reserveStr, err)
	}
	return nil
}

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Re-initialize the cgroup tree (cgroupslib Init) so nomad.slice/reserve and its cpuset.cpus exist.
  2. Ensure write access to /sys/fs/cgroup/nomad.slice/reserve/cpuset.cpus (root or delegated cgroups).
  3. Confirm the reserved cores are within the parent's cpuset.cpus.effective and offline cores are excluded.
  4. Restart the Nomad client to rebuild partition state if share/reserve writes are out of sync.

Example fix

// before: operator deleted the cgroup
$ sudo rm -rf /sys/fs/cgroup/nomad.slice/reserve
// after: restart nomad client so Init recreates the tree
$ sudo systemctl restart nomad
Defensive patterns

Strategy: retry

Validate before calling

func reservePathOK(p string) error {
  if _, err := os.Stat(p); err != nil { return err }
  return syscall.Access(p, syscall.W_OK)
}

Type guard

func reserveCoresUsable(reserve *idset.Set[hw.CoreID], usable *idset.Set[hw.CoreID]) bool {
  return usable.ContainsSet(reserve)
}

Try / catch

if err := partition.Release(cores); err != nil {
  if strings.Contains(err.Error(), "reserve cpuset") {
    // rebuild kernel state from in-memory partition
    if err := cgroupslib.Init(logger, coresStr); err != nil { return err }
    return partition.Release(cores)
  }
  return err
}

Prevention

When it happens

Trigger: os.WriteFile(p.reservePath, ...) fails during Reserve() or Release() — EACCES, ENOENT (reserve cgroup missing, e.g. Init not run or tree deleted), or EINVAL (core values invalid for the parent cpuset; an empty reserve string may also be rejected by some kernels).

Common situations: Client started without successful cgroup Init; operator manually removed nomad.slice/reserve; cgroup privileges lost (container runtime restrictions); reservation of cores whose ids are not present on the machine.

Related errors


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