hashicorp/nomad · error

Malformed ulimit specification %v: %v

Error message

Malformed ulimit specification %v: %v

What it means

After the colon check, sliceMergeUlimit splits the raw ulimit string on ":" and requires both soft and hard parts (the earlier implicit soft==soft expansion guarantees a colon, so this branch is a defensive fallback for strings like just ":" or malformed input). If SplitN yields fewer than 2 parts, the specification is rejected. This is input parsing, not a Docker API failure.

Source

Thrown at drivers/docker/driver.go:2131

	return newClient, merr.ErrorOrNil()
}

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

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Format ulimit values as "soft:hard", e.g. "1024:4096", or a single number for soft==hard.
  2. Trim whitespace from config values before submission.
  3. Ensure templating emits either a plain integer or integer:integer.
  4. Add a pre-submit linter for the driver's ulimit config keys.

Example fix

// before
ulimits = { core = ":" }
// after
ulimits = { core = "0:0" }
Defensive patterns

Strategy: validation

Validate before calling

parts := strings.SplitN(val, ":", 2)
if len(parts) != 2 { return fmt.Errorf("ulimit %q must be soft:hard", name) }

Prevention

When it happens

Trigger: A ulimit value that after normalization still has no two colon-separated parts — practically a value like ":" or edge-case input that slips past the len==0 and Contains(":") checks.

Common situations: Hand-edited config with stray whitespace-only values; over-engineered templating producing ":"; unusual values intended as something other than soft:hard pairs.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


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