{"record":{"id":"89e84ec58441c32f","repo":"hashicorp/nomad","slug":"malformed-ulimit-specification-v-v","errorCode":null,"errorMessage":"Malformed ulimit specification %v: %v","messagePattern":"Malformed ulimit specification (.+?): (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"drivers/docker/driver.go","lineNumber":2131,"sourceCode":"\n\treturn newClient, merr.ErrorOrNil()\n}\n\nfunc 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","sourceCodeStart":2113,"sourceCodeEnd":2149,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/drivers/docker/driver.go#L2113-L2149","documentation":"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.","triggerScenarios":"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.","commonSituations":"Hand-edited config with stray whitespace-only values; over-engineered templating producing \":\"; unusual values intended as something other than soft:hard pairs.","solutions":["Format ulimit values as \"soft:hard\", e.g. \"1024:4096\", or a single number for soft==hard.","Trim whitespace from config values before submission.","Ensure templating emits either a plain integer or integer:integer.","Add a pre-submit linter for the driver's ulimit config keys."],"exampleFix":"// before\nulimits = { core = \":\" }\n// after\nulimits = { core = \"0:0\" }","handlingStrategy":"validation","validationCode":"parts := strings.SplitN(val, \":\", 2)\nif len(parts) != 2 { return fmt.Errorf(\"ulimit %q must be soft:hard\", name) }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Format values strictly as integer or integer:integer.","Trim whitespace and strip stray colons from config values.","Lint job specs for ulimit format before submission."],"tags":["docker","ulimit","config-validation"],"backgroundTag":"invalid-config-value","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"}