hashicorp/nomad · error
ErrInvalidRange
ErrInvalidRange
Error message
lower bound cannot be greater than upper bound
What it means
ErrInvalidRange is returned by validateBounds when the parsed lower bound of a UID/GID range exceeds the upper bound, e.g. "10-1". Such a range is logically empty, so the validators package rejects it rather than producing a no-op or surprising idset behavior.
Source
Thrown at drivers/shared/validators/validators.go:20
// SPDX-License-Identifier: MPL-2.0
package validators
import (
"errors"
"fmt"
"strconv"
"strings"
"github.com/hashicorp/go-hclog"
"github.com/hashicorp/nomad/client/lib/idset"
"github.com/hashicorp/nomad/helper/users"
)
var (
ErrInvalidBound = errors.New("range bound not valid")
//ErrEmptyRange = errors.New("range value cannot be empty")
ErrInvalidRange = errors.New("lower bound cannot be greater than upper bound")
)
type (
// A GroupID (GID) represents a unique numerical value assigned to each user group.
GroupID uint64
// A UserID represents a unique numerical value assigned to each user account.
UserID uint64
)
type Validator struct {
// DeniedHostUids configures which host uids are disallowed
deniedUIDs *idset.Set[UserID]
// DeniedHostGids configures which host gids are disallowed
deniedGIDs *idset.Set[GroupID]
View on GitHub (pinned to 482b49bf1a)
Solutions
- Swap the endpoints so the lower value comes first, e.g. "1-10" instead of "10-1"
- Generate ranges programmatically (e.g. via idset helpers or templating) to guarantee ordering
- Add a pre-submit check in your config pipeline that asserts low <= high for each range
- Review the full range list in client config for other reversed entries
Example fix
// before bounds = "10-1" // after bounds = "1-10"
Defensive patterns
Strategy: validation
Validate before calling
func orderedRange(s string) error {
p := strings.Split(s, "-")
if len(p) != 2 { return errors.New("expected low-high") }
lo, err1 := strconv.ParseUint(p[0], 10, 32)
hi, err2 := strconv.ParseUint(p[1], 10, 32)
if err1 != nil || err2 != nil { return errors.New("bounds must be numeric") }
if lo > hi { return errors.New("lower bound must be <= upper bound") }
return nil
} Type guard
func isOrdered(lo, hi uint64) bool { return lo <= hi } Try / catch
if err := validators.ValidateBounds(cfg.Bounds); err != nil {
if errors.Is(err, validators.ErrInvalidRange) {
return fmt.Errorf("range %q endpoints are reversed; use low-high: %w", cfg.Bounds, err)
}
return err
} Prevention
- Write ranges as low-high consistently
- Generate ranges programmatically to guarantee ordering
- Review all UID/GID ranges after hand edits or merges
When it happens
Trigger: Passing a bounds string like "10-1" or "2000-1000" to validateBounds for allowed/disallowed UID/GID ranges; comparison of the two parsed endpoints triggers the error after both parse successfully.
Common situations: Reversed endpoints from hand-editing ranges; templating that swaps variables accidentally; merging range lists and flipping an ordering; copy-paste from docs where ranges were listed descending.
Related errors
- ErrInvalidBound
- missing secret ID
- namespace cannot contain template delimiters or parenthesis
- wait config is nil or empty
- CSI.ControllerAttachVolume: VolumeID is required
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/bfe0d14cf657f88a.
Report an issue: GitHub.