hashicorp/nomad · error

driver does not allow the following capabilities: %s

Error message

driver does not allow the following capabilities: %s

What it means

capabilities.Calculate intersects the driver-configured allowed capability set (allowCaps) with the capabilities a task requests via cap_add. If the task requests any capability outside the driver's allowlist, Calculate returns 'driver does not allow the following capabilities: <list>'. This enforces the Nomad allow_caps driver/plugin configuration security boundary.

Source

Thrown at drivers/shared/capabilities/defaults.go:146

// capabilities specified in cap_add. The task will not be allowed to add capabilities
// not set in the allow_caps setting (which by default is the same as the basis).
//
// cap_add takes precedence over cap_drop, enabling the common pattern of dropping
// all capabilities, then adding back the desired smaller set. e.g.
//
//	cap_drop = ["all"]
//	cap_add = ["chown", "kill"]
//
// Note that the resulting capability names are upper-cased and prefixed with
// "CAP_", which is the expected input for the exec/java driver implementation.
func Calculate(basis *Set, allowCaps, capAdd, capDrop []string) ([]string, error) {
	allow := New(allowCaps)
	adds := New(capAdd)

	// determine caps the task wants that are not allowed
	missing := allow.Difference(adds)
	if !missing.Empty() {
		return nil, fmt.Errorf("driver does not allow the following capabilities: %s", missing)
	}

	// the realized enabled capabilities starts with what is allowed both by driver
	// config AND is a member of the basis (i.e. nomad defaults)
	result := basis.Intersect(allow)

	// then remove capabilities the task explicitly drops
	result.Remove(capDrop)

	// then add back capabilities the task explicitly adds
	return result.Union(adds).Slice(true), nil
}

// Delta calculates the set of capabilities that must be added and dropped relative
// to a basis to achieve a desired result. The use case is that the docker driver
// assumes a default set (DockerDefault), and we must calculate what to pass into
// --cap-add and --cap-drop on container creation given the inputs of the docker
// plugin config for allow_caps, and the docker task configuration for cap_add and

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Remove the disallowed capabilities from the task's cap_add
  2. Ask the cluster operator to add the needed capability to the docker plugin's allow_caps in client config
  3. Align with the least-privilege default set Nomad permits (basis) instead of requesting broad caps

Example fix

// before
cap_add = ["SYS_ADMIN"]
// after
cap_add = ["NET_BIND_SERVICE"]
Defensive patterns

Strategy: validation

Validate before calling

allowed, err := capabilities.Calculate(driverAllowCaps, taskCapAdd)
if err != nil {
    // trim taskCapAdd to allowed set before StartTask
    taskCapAdd = intersection(taskCapAdd, driverAllowCaps)
}

Try / catch

if _, err := capabilities.Calculate(allowCaps, capAdd); err != nil {
    var missingCaps string
    fmt.Sscanf(err.Error(), "driver does not allow the following capabilities: %s", &missingCaps)
    // reduce requested caps or update plugin allow_caps
}

Prevention

When it happens

Trigger: StartTask (docker driver container config) where the task's cap_add contains caps not present in the driver's allow_caps config (or the plugin's default allowlist).

Common situations: Job asks for cap_add = ["SYS_ADMIN"] or "ALL" while the client's docker plugin allow_caps only permits e.g. NET_BIND_SERVICE/CHOWN/DAC_OVERRIDE; operator tightened allow_caps without updating jobs.

Related errors


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