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

  1. Use exactly `--set must` or `--set all`
  2. 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
  3. 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

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


AI-assisted analysis of juanfont/headscale@565fd254d0 (2026-08-15). Data as JSON: /api/errors/1aa0df99a924f497. Report an issue: GitHub.