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

  1. Swap the endpoints so the lower value comes first, e.g. "1-10" instead of "10-1"
  2. Generate ranges programmatically (e.g. via idset helpers or templating) to guarantee ordering
  3. Add a pre-submit check in your config pipeline that asserts low <= high for each range
  4. 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

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


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