{"record":{"id":"07db31006365e4e7","repo":"hashicorp/nomad","slug":"dynamic-user-min-must-be-set","errorCode":null,"errorMessage":"dynamic_user_min must be set","messagePattern":"dynamic_user_min must be set","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nomad/structs/config/users.go","lineNumber":65,"sourceCode":"\n// Equal returns whether u and o are the same.\nfunc (u *UsersConfig) Equal(o *UsersConfig) bool {\n\tif u == nil || o == nil {\n\t\treturn u == o\n\t}\n\tswitch {\n\tcase !pointer.Eq(u.MinDynamicUser, o.MinDynamicUser):\n\t\treturn false\n\tcase !pointer.Eq(u.MaxDynamicUser, o.MaxDynamicUser):\n\t\treturn false\n\tdefault:\n\t\treturn true\n\t}\n}\n\nvar (\n\terrUsersUnset            = errors.New(\"users must not be nil\")\n\terrDynamicUserMinUnset   = errors.New(\"dynamic_user_min must be set\")\n\terrDynamicUserMinInvalid = errors.New(\"dynamic_user_min must not be negative\")\n\terrDynamicUserMaxUnset   = errors.New(\"dynamic_user_max must be set\")\n\terrDynamicUserMaxInvalid = errors.New(\"dynamic_user_max must not be negative\")\n)\n\n// Validate whether UsersConfig is valid.\n//\n// Note that -1 is a valid value for min/max dynamic users, as this is used\n// to indicate the dynamic workload users feature should be disabled.\nfunc (u *UsersConfig) Validate() error {\n\tif u == nil {\n\t\treturn errUsersUnset\n\t}\n\tif u.MinDynamicUser == nil {\n\t\treturn errDynamicUserMinUnset\n\t}\n\tif *u.MinDynamicUser < -1 {\n\t\treturn errDynamicUserMinInvalid","sourceCodeStart":47,"sourceCodeEnd":83,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/nomad/structs/config/users.go#L47-L83","documentation":"errDynamicUserMinUnset is returned by UsersConfig.Validate() when MinDynamicUser is a nil pointer. The dynamic workload users feature requires an explicit minimum UID, so an unset pointer is treated as a configuration error rather than a default. (-1 is valid and means \"disabled\", but nil means \"not configured\".)","triggerScenarios":"UsersConfig constructed with MinDynamicUser left nil (e.g. only setting MaxDynamicUser in the users config block) and then passed through Validate() during agent config parsing.","commonSituations":"Partially filled users config in HCL where dynamic_user_min was omitted; JSON/config decode that maps missing keys to nil pointers; test fixtures that only set one bound.","solutions":["Set `dynamic_user_min` in the users config block (an integer >= -1); use -1 to disable the feature.","Initialize MinDynamicUser programmatically when building UsersConfig in code.","Match with errors.Is(err, errDynamicUserMinUnset) in tests to verify the missing-field case."],"exampleFix":"// HCL before\nusers {\n  dynamic_user_max = 1500\n}\n\n// HCL after\nusers {\n  dynamic_user_min = 1000\n  dynamic_user_max = 1500\n}","handlingStrategy":"validation","validationCode":"if u != nil && u.MinDynamicUser == nil {\n    return fmt.Errorf(\"dynamic_user_min must be set (use -1 to disable)\")\n}","typeGuard":null,"tryCatchPattern":"if err := u.Validate(); err != nil {\n    if errors.Is(err, errDynamicUserMinUnset) {\n        return fmt.Errorf(\"set dynamic_user_min in the users config block\")\n    }\n    return err\n}","preventionTips":["Set both dynamic_user_min and dynamic_user_max together; -1 disables the feature.","Keep config templates with explicit defaults for both fields.","Cover the missing-min case in config validation tests."],"tags":["nomad","agent-config","validation"],"backgroundTag":"missing-required-argument","analyzedSha":"482b49bf1aec006f089bcfc7e632d8f6ac303e5e","analyzedAt":"2026-09-04T07:54:14.808Z","contentChangedAt":"2026-09-04T07:54:14.808Z","schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}