hashicorp/nomad · error

Malformed soft ulimit

Error message

Malformed soft ulimit %v: %v

What it means

The soft (first) component of the "soft:hard" ulimit string must be an integer; strconv.Atoi on splitted[0] failing triggers this error. The raw value is included so the developer can see the offending string. Raised during task config parsing before container creation.

Solutions

  1. Use plain decimal integers: ulimits = { nofile = "1048576:1048576" }.
  2. Replace "unlimited" with -1 (Docker's convention for unlimited).
  3. Strip units/suffixes — ulimits are counts, not sizes.
  4. Validate each colon-separated part with strconv.Atoi in a pre-flight check.

Example fix

// before
ulimits = { memlock = "unlimited:unlimited" }
// after
ulimits = { memlock = "-1:-1" }
Defensive patterns

Strategy: validation

Validate before calling

parts := strings.SplitN(val, ":", 2)
if _, err := strconv.Atoi(strings.TrimSpace(parts[0])); err != nil {
    return fmt.Errorf("ulimit %q soft value %q is not an integer", name, parts[0])
}

Prevention

When it happens

Trigger: ulimit value like "abc:4096", "10_24:4096", "0x100:4096", or "1024.5:4096" where the soft part isn't a decimal integer.

Common situations: Confusing ulimits with other byte/size formats (e.g. "1gb", "unlimited"); copy-pasting Kubernetes-style quantities; typos in numeric values.

Understand the failure class

Related errors


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

Appendix: source

Thrown at drivers/docker/driver.go:2135

func sliceMergeUlimit(ulimitsRaw map[string]string) ([]*containerapi.Ulimit, error) {
	var ulimits []*containerapi.Ulimit

	for name, ulimitRaw := range ulimitsRaw {
		if len(ulimitRaw) == 0 {
			return []*containerapi.Ulimit{}, fmt.Errorf("Malformed ulimit specification %v: %q, cannot be empty", name, ulimitRaw)
		}
		// hard limit is optional
		if !strings.Contains(ulimitRaw, ":") {
			ulimitRaw = ulimitRaw + ":" + ulimitRaw
		}

		splitted := strings.SplitN(ulimitRaw, ":", 2)
		if len(splitted) < 2 {
			return []*containerapi.Ulimit{}, fmt.Errorf("Malformed ulimit specification %v: %v", name, ulimitRaw)
		}
		soft, err := strconv.Atoi(splitted[0])
		if err != nil {
			return []*containerapi.Ulimit{}, fmt.Errorf("Malformed soft ulimit %v: %v", name, ulimitRaw)
		}
		hard, err := strconv.Atoi(splitted[1])
		if err != nil {
			return []*containerapi.Ulimit{}, fmt.Errorf("Malformed hard ulimit %v: %v", name, ulimitRaw)
		}

		ulimit := &containerapi.Ulimit{
			Name: name,
			Soft: int64(soft),
			Hard: int64(hard),
		}
		ulimits = append(ulimits, ulimit)
	}
	return ulimits, nil
}

func isDockerTransientError(err error) bool {
	if err == nil {

View on GitHub (pinned to 482b49bf1a)