hashicorp/nomad · error

bug: users pool min must be >= 0

Error message

bug: users pool min must be >= 0

What it means

New validates that PoolConfig.MinUGID is not negative; UGIDs are non-negative OS user/group IDs, so a negative min is a caller bug and panics. The pool maps tasks to UGID ranges and cannot represent negative IDs.

Source

Thrown at helper/users/dynamic/pool.go:82

}

// 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),
	}
}

// noopPool is an implementation of Pool that does not allow acquiring ugids
type noopPool struct{}

func (*noopPool) Restore(UGID) {}

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Set MinUGID to a non-negative value (typically >= 0 and <= MaxUGID)
  2. Use the documented disable mechanism instead of negative values to turn the pool off
  3. Validate user-supplied configuration (job/agent config) before constructing the PoolConfig

Example fix

// before
cfg := &dynamic.PoolConfig{MinUGID: -1, MaxUGID: 100_000}
// after
cfg := &dynamic.PoolConfig{MinUGID: 100_000, MaxUGID: 200_000}
Defensive patterns

Strategy: validation

Validate before calling

if cfg != nil && cfg.MinUGID < 0 { return fmt.Errorf("MinUGID must be >= 0, got %d", cfg.MinUGID) }

Try / catch

defer func() { if r := recover(); r != nil { if s, ok := r.(string); ok && strings.Contains(s, "users pool min must be >= 0") { log.Fatalf("invalid MinUGID: %v", s) }; panic(r) } }()

Prevention

When it happens

Trigger: Calling users/dynamic.New with a PoolConfig whose MinUGID < 0 (e.g. -1 used as a sentinel for 'unset').

Common situations: Using -1 or 0-minus values as a placeholder in config files or structs, arithmetic overflow when computing the UGID range, or misreading doNotEnable sentinel semantics.

Related errors


AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04). Data as JSON: /api/errors/7bafa103fff03f3d. Report an issue: GitHub.