juanfont/headscale · error · errUnknownSet
%w: %q
Error message
%w: %q
What it means
Sentinel error errUnknownSet returned by `hi list-versions --set <value>` when the value is neither "must" nor "all". The command enumerates Tailscale versions from capver.SupportedMajorMinorVersions plus "head"/"unstable"; only two named sets are predefined (must = first four plus last two of that list).
Source
Thrown at cmd/hi/listversions.go:45
// listVersions prints the Tailscale versions used by integration tests
// in a format CI can shell out to. Mirrors integration/scenario.go
// AllVersions and MustTestVersions: "head" and "unstable" are bare
// tags, releases get a "v" prefix so each entry can be appended to
// "ghcr.io/tailscale/tailscale:" directly.
func listVersions(env *command.Env) error {
release := capver.TailscaleLatestMajorMinor(capver.SupportedMajorMinorVersions, true)
all := append([]string{"head", "unstable"}, release...)
must := append(append([]string{}, all[0:4]...), all[len(all)-2:]...)
var versions []string
switch listVersionsConfig.Set {
case "must":
versions = must
case "all":
versions = all
default:
return fmt.Errorf("%w: %q", errUnknownSet, listVersionsConfig.Set)
}
excluded := make(map[string]bool)
if listVersionsConfig.Exclude != "" {
for v := range strings.SplitSeq(listVersionsConfig.Exclude, ",") {
excluded[strings.TrimSpace(v)] = true
}
}
out := make([]string, 0, len(versions))
for _, v := range versions {
if excluded[v] {
continue
}
if v != "head" && v != "unstable" {View on GitHub (pinned to 565fd254d0)
Solutions
- Use exactly `--set must` or `--set all`
- Run `go run ./cmd/hi list-versions --set all` to see the full version list and pick exclusions via --exclude instead of inventing set names
- Check for trailing whitespace or shell quoting around the flag value in scripts
Example fix
# before go run ./cmd/hi list-versions --set supported # after go run ./cmd/hi list-versions --set all --exclude 1.30,1.32
Defensive patterns
Strategy: validation
Validate before calling
validSets := map[string]bool{"must": true, "all": true}
if !validSets[listVersionsConfig.Set] {
return fmt.Errorf("--set must be one of %v", maps.Keys(validSets))
} Type guard
func isValidVersionSet(s string) bool {
return s == "must" || s == "all"
} Prevention
- Pin --set to a literal value in scripts; never pass an unchecked variable
- Remember the value is case-sensitive with no aliases
- Use --exclude to trim the 'all' set instead of inventing new set names
When it happens
Trigger: Passing --set anything other than exactly "must" or "all" (e.g. --set required, --set Must, --set "") — the switch on listVersionsConfig.Set falls to the default branch.
Common situations: Typos or case mismatch ("All" vs "all"); assuming a set name like "supported" or "stable" exists; scripting the flag with an empty variable.
Related errors
- HEADSCALE_CLI_API_KEY environment variable needs to be set
- failed to parse ApiKey
- failed to parse oauth client secret
- failed to parse oauth access token
- failed to parse auth-key
AI-assisted analysis of juanfont/headscale@565fd254d0 (2026-08-15).
Data as JSON: /api/errors/1aa0df99a924f497.
Report an issue: GitHub.