{"record":{"id":"ed440e44cf6ebbe7","repo":"hashicorp/nomad","slug":"bug-users-pool-cannot-be-nil","errorCode":null,"errorMessage":"bug: users pool cannot be nil","messagePattern":"bug: users pool cannot be nil","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"helper/users/dynamic/pool.go","lineNumber":76,"sourceCode":"type PoolConfig struct {\n\t// MinUGID is the minimum value for a UGID allocated from the pool.\n\tMinUGID int\n\n\t// MaxUGID is the maximum value for a UGID allocated from the pool.\n\tMaxUGID int\n}\n\n// disable will return true if either min or max is set to Disable (-1),\n// indicating the client should not enable the dynamic workload users\n// functionality\nfunc (p *PoolConfig) disable() bool {\n\treturn p.MinUGID == doNotEnable || p.MaxUGID == doNotEnable\n}\n\n// New creates a Pool with the given PoolConfig options.\nfunc New(opts *PoolConfig) Pool {\n\tif opts == nil {\n\t\tpanic(\"bug: users pool cannot be nil\")\n\t}\n\tif opts.disable() {\n\t\treturn new(noopPool)\n\t}\n\tif opts.MinUGID < 0 {\n\t\tpanic(\"bug: users pool min must be >= 0\")\n\t}\n\tif opts.MaxUGID < opts.MinUGID {\n\t\tpanic(\"bug: users pool max must be >= min\")\n\t}\n\t// a small but reasonable number of tasks to expect\n\tconst defaultPoolCapacity = 32\n\treturn &pool{\n\t\tmin:  UGID(opts.MinUGID),\n\t\tmax:  UGID(opts.MaxUGID),\n\t\tlock: new(sync.Mutex),\n\t\tused: set.New[UGID](defaultPoolCapacity),\n\t}","sourceCodeStart":58,"sourceCodeEnd":94,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/helper/users/dynamic/pool.go#L58-L94","documentation":"users/dynamic.New(opts) requires a non-nil *PoolConfig; passing nil is treated as a caller bug and panics with this message. A nil config provides no UGID range, so the pool cannot be constructed safely. The 'bug:' prefix indicates it should only happen from incorrect library usage, not environmental conditions.","triggerScenarios":"Calling users/dynamic.New(nil) directly, or via pool.NewClient / helpers that pass an uninitialized *PoolConfig pointer.","commonSituations":"Declaring a *PoolConfig variable without initializing it, conditional config loading that leaves the pointer nil, or wiring errors in client setup code.","solutions":["Pass a valid &users dynamic.PoolConfig{} with MinUGID and MaxUGID set before calling New","Add a nil-check in your own config-loading path and fall back to sane defaults","If the pool should be disabled, use PoolConfig fields that make disable() true rather than passing nil"],"exampleFix":"// before\nvar cfg *dynamic.PoolConfig\npool := dynamic.New(cfg)\n// after\ncfg := &dynamic.PoolConfig{MinUGID: 100_000, MaxUGID: 200_000}\npool := dynamic.New(cfg)","handlingStrategy":"validation","validationCode":"func validPoolConfig(cfg *dynamic.PoolConfig) bool { return cfg != nil && cfg.MinUGID >= 0 && cfg.MaxUGID >= cfg.MinUGID }","typeGuard":"func cfgNotNil(cfg *dynamic.PoolConfig) bool { return cfg != nil }","tryCatchPattern":"defer func() { if r := recover(); r != nil { if s, ok := r.(string); ok && strings.Contains(s, \"users pool cannot be nil\") { log.Fatalf(\"nil PoolConfig passed to dynamic.New\") }; panic(r) } }()","preventionTips":["Initialize PoolConfig at declaration with field values","Never pass nil as a 'default' — construct a struct with the library's documented disable mechanism","Add nil-checks in your config loader"],"tags":["panic","configuration","nil-pointer"],"backgroundTag":"nil-config-argument","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"}