{"record":{"id":"2b43b6860b774464","repo":"hashicorp/nomad","slug":"malformed-soft-ulimit-v-v","errorCode":null,"errorMessage":"Malformed soft ulimit %v: %v","messagePattern":"Malformed soft ulimit (.+?): (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"drivers/docker/driver.go","lineNumber":2135,"sourceCode":"func sliceMergeUlimit(ulimitsRaw map[string]string) ([]*containerapi.Ulimit, error) {\n\tvar ulimits []*containerapi.Ulimit\n\n\tfor name, ulimitRaw := range ulimitsRaw {\n\t\tif len(ulimitRaw) == 0 {\n\t\t\treturn []*containerapi.Ulimit{}, fmt.Errorf(\"Malformed ulimit specification %v: %q, cannot be empty\", name, ulimitRaw)\n\t\t}\n\t\t// hard limit is optional\n\t\tif !strings.Contains(ulimitRaw, \":\") {\n\t\t\tulimitRaw = ulimitRaw + \":\" + ulimitRaw\n\t\t}\n\n\t\tsplitted := strings.SplitN(ulimitRaw, \":\", 2)\n\t\tif len(splitted) < 2 {\n\t\t\treturn []*containerapi.Ulimit{}, fmt.Errorf(\"Malformed ulimit specification %v: %v\", name, ulimitRaw)\n\t\t}\n\t\tsoft, err := strconv.Atoi(splitted[0])\n\t\tif err != nil {\n\t\t\treturn []*containerapi.Ulimit{}, fmt.Errorf(\"Malformed soft ulimit %v: %v\", name, ulimitRaw)\n\t\t}\n\t\thard, err := strconv.Atoi(splitted[1])\n\t\tif err != nil {\n\t\t\treturn []*containerapi.Ulimit{}, fmt.Errorf(\"Malformed hard ulimit %v: %v\", name, ulimitRaw)\n\t\t}\n\n\t\tulimit := &containerapi.Ulimit{\n\t\t\tName: name,\n\t\t\tSoft: int64(soft),\n\t\t\tHard: int64(hard),\n\t\t}\n\t\tulimits = append(ulimits, ulimit)\n\t}\n\treturn ulimits, nil\n}\n\nfunc isDockerTransientError(err error) bool {\n\tif err == nil {","sourceCodeStart":2117,"sourceCodeEnd":2153,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/drivers/docker/driver.go#L2117-L2153","documentation":"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.","triggerScenarios":"ulimit value like \"abc:4096\", \"10_24:4096\", \"0x100:4096\", or \"1024.5:4096\" where the soft part isn't a decimal integer.","commonSituations":"Confusing ulimits with other byte/size formats (e.g. \"1gb\", \"unlimited\"); copy-pasting Kubernetes-style quantities; typos in numeric values.","solutions":["Use plain decimal integers: ulimits = { nofile = \"1048576:1048576\" }.","Replace \"unlimited\" with -1 (Docker's convention for unlimited).","Strip units/suffixes — ulimits are counts, not sizes.","Validate each colon-separated part with strconv.Atoi in a pre-flight check."],"exampleFix":"// before\nulimits = { memlock = \"unlimited:unlimited\" }\n// after\nulimits = { memlock = \"-1:-1\" }","handlingStrategy":"validation","validationCode":"parts := strings.SplitN(val, \":\", 2)\nif _, err := strconv.Atoi(strings.TrimSpace(parts[0])); err != nil {\n    return fmt.Errorf(\"ulimit %q soft value %q is not an integer\", name, parts[0])\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use decimal integers only; use -1 for unlimited, never the word \"unlimited\".","Don't paste size formats (\"1gb\") or Kubernetes quantities into ulimit values.","Atoi-check both soft and hard parts before submitting config."],"tags":["docker","ulimit","config-validation"],"backgroundTag":"invalid-numeric-format","analyzedSha":"482b49bf1aec006f089bcfc7e632d8f6ac303e5e","analyzedAt":"2026-09-04T07:54:14.808Z","contentChangedAt":"2026-09-04T07:54:14.808Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}