{"record":{"id":"bfe0d14cf657f88a","repo":"hashicorp/nomad","slug":"errinvalidrange","errorCode":"ErrInvalidRange","errorMessage":"lower bound cannot be greater than upper bound","messagePattern":"lower bound cannot be greater than upper bound","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"drivers/shared/validators/validators.go","lineNumber":20,"sourceCode":"// SPDX-License-Identifier: MPL-2.0\n\npackage validators\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/hashicorp/go-hclog\"\n\t\"github.com/hashicorp/nomad/client/lib/idset\"\n\t\"github.com/hashicorp/nomad/helper/users\"\n)\n\nvar (\n\tErrInvalidBound = errors.New(\"range bound not valid\")\n\t//ErrEmptyRange   = errors.New(\"range value cannot be empty\")\n\tErrInvalidRange = errors.New(\"lower bound cannot be greater than upper bound\")\n)\n\ntype (\n\n\t// A GroupID (GID) represents a unique numerical value assigned to each user group.\n\tGroupID uint64\n\n\t// A UserID represents a unique numerical value assigned to each user account.\n\tUserID uint64\n)\n\ntype Validator struct {\n\t// DeniedHostUids configures which host uids are disallowed\n\tdeniedUIDs *idset.Set[UserID]\n\n\t// DeniedHostGids configures which host gids are disallowed\n\tdeniedGIDs *idset.Set[GroupID]\n","sourceCodeStart":2,"sourceCodeEnd":38,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/drivers/shared/validators/validators.go#L2-L38","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nbounds = \"10-1\"\n// after\nbounds = \"1-10\"","handlingStrategy":"validation","validationCode":"func orderedRange(s string) error {\n    p := strings.Split(s, \"-\")\n    if len(p) != 2 { return errors.New(\"expected low-high\") }\n    lo, err1 := strconv.ParseUint(p[0], 10, 32)\n    hi, err2 := strconv.ParseUint(p[1], 10, 32)\n    if err1 != nil || err2 != nil { return errors.New(\"bounds must be numeric\") }\n    if lo > hi { return errors.New(\"lower bound must be <= upper bound\") }\n    return nil\n}","typeGuard":"func isOrdered(lo, hi uint64) bool { return lo <= hi }","tryCatchPattern":"if err := validators.ValidateBounds(cfg.Bounds); err != nil {\n    if errors.Is(err, validators.ErrInvalidRange) {\n        return fmt.Errorf(\"range %q endpoints are reversed; use low-high: %w\", cfg.Bounds, err)\n    }\n    return err\n}","preventionTips":["Write ranges as low-high consistently","Generate ranges programmatically to guarantee ordering","Review all UID/GID ranges after hand edits or merges"],"tags":["validation","uid-gid","ranges","nomad"],"backgroundTag":"invalid-numeric-range","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"}