hashicorp/nomad · error

cap_add configured with capabilities not supported by system

Error message

cap_add configured with capabilities not supported by system: %s

What it means

TaskConfig.validate() checks each entry in cap_add against capabilities.Supported(); any capability the host kernel doesn't support causes the task to be rejected. This stops tasks from requesting privileges the system cannot enforce or grant.

Source

Thrown at drivers/exec/driver.go:235

}

func (tc *TaskConfig) validate() error {
	switch tc.ModePID {
	case "", executor.IsolationModePrivate, executor.IsolationModeHost:
	default:
		return fmt.Errorf("pid_mode must be %q or %q, got %q", executor.IsolationModePrivate, executor.IsolationModeHost, tc.ModePID)
	}

	switch tc.ModeIPC {
	case "", executor.IsolationModePrivate, executor.IsolationModeHost:
	default:
		return fmt.Errorf("ipc_mode must be %q or %q, got %q", executor.IsolationModePrivate, executor.IsolationModeHost, tc.ModeIPC)
	}

	supported := capabilities.Supported()
	badAdds := supported.Difference(capabilities.New(tc.CapAdd))
	if !badAdds.Empty() {
		return fmt.Errorf("cap_add configured with capabilities not supported by system: %s", badAdds)
	}

	badDrops := supported.Difference(capabilities.New(tc.CapDrop))
	if !badDrops.Empty() {
		return fmt.Errorf("cap_drop configured with capabilities not supported by system: %s", badDrops)
	}

	if tc.WorkDir != "" && !filepath.IsAbs(tc.WorkDir) {
		return fmt.Errorf("work_dir must be absolute but got relative path %q", tc.WorkDir)
	}

	return nil
}

// TaskState is the state which is encoded in the handle returned in
// StartTask. This information is needed to rebuild the task state and handler
// during recovery.
type TaskState struct {

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Remove or correct the unsupported capability listed in the error
  2. Check `capsh --print` on the client to see the host's supported capabilities
  3. Use a client constraint to place the job on hosts supporting the needed caps

Example fix

// before
config {
  cap_add = ["CAP_SYS_PTRACE"]
}
// after
config {
  cap_add = []
}
Defensive patterns

Strategy: validation

Validate before calling

for _, c := range tc.CapAdd {
  if !hostSupportedCaps[c] {
    return fmt.Errorf("cap_add unsupported: %s", c)
  }
}

Type guard

func capsSupported(caps []string) bool {
  return capabilities.Supported().Difference(capabilities.New(caps)).Empty()
}

Try / catch

if err := task.Validate(); err != nil {
  if strings.Contains(err.Error(), "cap_add") {
    cfg.CapAdd = nil
  }
  return err
}

Prevention

When it happens

Trigger: Task config with cap_add containing an unknown/unsupported capability name (typo, unsupported on kernel, or name not present in the host's bounding set reported by capabilities.Supported()).

Common situations: Running on kernels older than a capability's introduction; typos like "CAP_NET_ADMIN" vs "net_admin" mismatch; exec-in-exec environments where the bounding set is reduced.

Related errors


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