hashicorp/nomad · error

failed to parse ulimit configuration: %v

Error message

failed to parse ulimit configuration: %v

What it means

The ulimit option is parsed by sliceMergeUlimit, which expects entries of the form name=soft:hard (or name=soft). Malformed entries, unknown limit names, or values that fail integer parsing cause this wrapped error before any Docker API call.

Source

Thrown at drivers/docker/driver.go:1396

	hostConfig.UTSMode = containerapi.UTSMode(driverConfig.UTSMode)

	if usernsErr := d.validateNamespace(d.config.AllowedModes.Userns, "userns_mode", driverConfig.UsernsMode); usernsErr != nil {
		return c, usernsErr
	}
	hostConfig.UsernsMode = containerapi.UsernsMode(driverConfig.UsernsMode)

	hostConfig.ExtraHosts = driverConfig.ExtraHosts
	hostConfig.SecurityOpt = driverConfig.SecurityOpt
	hostConfig.Sysctls = driverConfig.Sysctl

	hostConfig.SecurityOpt, err = parseSecurityOpts(driverConfig.SecurityOpt)
	if err != nil {
		return c, fmt.Errorf("failed to parse security_opt configuration: %v", err)
	}

	ulimits, err := sliceMergeUlimit(driverConfig.Ulimit)
	if err != nil {
		return c, fmt.Errorf("failed to parse ulimit configuration: %v", err)
	}
	hostConfig.Ulimits = ulimits

	hostConfig.ReadonlyRootfs = driverConfig.ReadonlyRootfs

	// set the docker network mode
	hostConfig.NetworkMode = containerapi.NetworkMode(driverConfig.NetworkMode)

	// if the driver config does not specify a network mode then try to use the
	// shared alloc network
	if hostConfig.NetworkMode == "" {
		if task.NetworkIsolation != nil && task.NetworkIsolation.Path != "" {
			// find the previously created parent container to join networks with
			netMode := fmt.Sprintf("container:%s", task.NetworkIsolation.Labels[dockerNetSpecLabelKey])
			logger.Debug("configuring network mode for task group", "network_mode", netMode)
			hostConfig.NetworkMode = containerapi.NetworkMode(netMode)
		} else {
			// docker default

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Write each ulimit as name=soft:hard, e.g. ulimit = ["nofile=65536:65536"]
  2. Check for missing '=' or ':' and non-numeric values in every entry
  3. Refer to Docker's --ulimit documentation for valid names and syntax

Example fix

// before
driver {
  docker {
    ulimit = ["nofile 65536"]
  }
}
// after
driver {
  docker {
    ulimit = ["nofile=65536:65536"]
  }
}
Defensive patterns

Strategy: validation

Validate before calling

re := regexp.MustCompile(`^[a-zA-Z]+=(\d+)?(:\d+)?$`)
for _, u := range cfg.Ulimit {
  if !re.MatchString(u) {
    return fmt.Errorf("ulimit must be name=soft:hard, got %q", u)
  }
}

Try / catch

err := client.StartTask(task); if err != nil && strings.Contains(err.Error(), "failed to parse ulimit") { logOffendingUlimits(cfg.Ulimit) }

Prevention

When it happens

Trigger: StartTask -> createContainerConfig calls sliceMergeUlimit(driverConfig.Ulimit) and any ulimit string lacks '=', has a non-integer soft/hard value, or uses an invalid range (soft > hard is accepted by Docker but parsing errors are not).

Common situations: Writing 'ulimit { nofile = 65536 }' (map syntax) instead of the expected list entries like "nofile=65536:65536"; omitting the '=' or the colon separator; typos in the limit name.

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/c212643a024a0b52. Report an issue: GitHub.