hashicorp/nomad · error
bug: users pool cannot be nil
Error message
bug: users pool cannot be nil
What it means
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.
Source
Thrown at helper/users/dynamic/pool.go:76
type PoolConfig struct {
// MinUGID is the minimum value for a UGID allocated from the pool.
MinUGID int
// MaxUGID is the maximum value for a UGID allocated from the pool.
MaxUGID int
}
// disable will return true if either min or max is set to Disable (-1),
// indicating the client should not enable the dynamic workload users
// functionality
func (p *PoolConfig) disable() bool {
return p.MinUGID == doNotEnable || p.MaxUGID == doNotEnable
}
// New creates a Pool with the given PoolConfig options.
func New(opts *PoolConfig) Pool {
if opts == nil {
panic("bug: users pool cannot be nil")
}
if opts.disable() {
return new(noopPool)
}
if opts.MinUGID < 0 {
panic("bug: users pool min must be >= 0")
}
if opts.MaxUGID < opts.MinUGID {
panic("bug: users pool max must be >= min")
}
// a small but reasonable number of tasks to expect
const defaultPoolCapacity = 32
return &pool{
min: UGID(opts.MinUGID),
max: UGID(opts.MaxUGID),
lock: new(sync.Mutex),
used: set.New[UGID](defaultPoolCapacity),
}View on GitHub (pinned to 482b49bf1a)
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
Example fix
// before
var cfg *dynamic.PoolConfig
pool := dynamic.New(cfg)
// after
cfg := &dynamic.PoolConfig{MinUGID: 100_000, MaxUGID: 200_000}
pool := dynamic.New(cfg) Defensive patterns
Strategy: validation
Validate before calling
func validPoolConfig(cfg *dynamic.PoolConfig) bool { return cfg != nil && cfg.MinUGID >= 0 && cfg.MaxUGID >= cfg.MinUGID } Type guard
func cfgNotNil(cfg *dynamic.PoolConfig) bool { return cfg != nil } Try / catch
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) } }() Prevention
- 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
When it happens
Trigger: Calling users/dynamic.New(nil) directly, or via pool.NewClient / helpers that pass an uninitialized *PoolConfig pointer.
Common situations: Declaring a *PoolConfig variable without initializing it, conditional config loading that leaves the pointer nil, or wiring errors in client setup code.
Related errors
- nil config passed
- nil config passed for internal plugin %s
- No Keyloader object to perform LoadKeyPair
- bug: users pool min must be >= 0
- bug: users pool max must be >= min
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/ed440e44cf6ebbe7.
Report an issue: GitHub.