tailscale/tailscale · error
parseVersion: parsing %q: %w
Error message
parseVersion: parsing %q: %w
What it means
The second parseVersion failure mode: there were exactly three dot-separated parts, but at least one is not a plain integer (strconv.Atoi failed on it). Typical culprits: a 'v' prefix ('v1.72.0'), an empty part ('1..0'), a sign, or trailing characters like '0-rc1'. Input comes from VERSION.txt or TS_VERSION_OVERRIDE.
Source
Thrown at version/mkversion/mkversion.go:468
patch: patch,
changeCount: changeCount,
hash: hash,
date: date,
}, nil
}
func parseVersion(s string) (major, minor, patch int, err error) {
fs := strings.Split(strings.TrimSpace(s), ".")
if len(fs) != 3 {
err = fmt.Errorf("parseVersion: parsing %q: wrong number of parts: %d", s, len(fs))
return
}
ints := make([]int, 0, 3)
for _, s := range fs {
var i int
i, err = strconv.Atoi(s)
if err != nil {
err = fmt.Errorf("parseVersion: parsing %q: %w", s, err)
return
}
ints = append(ints, i)
}
return ints[0], ints[1], ints[2], nil
}
func shortHash(hash string) string {
if len(hash) < 9 {
return hash
}
return hash[:9]
}
// dirRunner executes commands in the specified dir.
type dirRunner string
func (r dirRunner) output(prog string, args ...string) (string, error) {View on GitHub (pinned to 6e0912f979)
Solutions
- Strip the 'v' prefix and any pre-release suffix before setting TS_VERSION_OVERRIDE
- Correct VERSION.txt so every part is digits only
- Add a guard in your release script: `[[ $TS_VERSION_OVERRIDE =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]`
Example fix
# before export TS_VERSION_OVERRIDE=v1.72.0 # 'v1' is not an int # after export TS_VERSION_OVERRIDE=1.72.0
Defensive patterns
Strategy: validation
Validate before calling
// Reject versions whose parts are not plain integers.
var strictVersion = regexp.MustCompile(`^\d+\.\d+\.\d+$`)
if o := os.Getenv("TS_VERSION_OVERRIDE"); o != "" && !strictVersion.MatchString(o) {
log.Fatalf("TS_VERSION_OVERRIDE must match \\(major.minor.patch\\) digits only, got %q", o)
} Type guard
func isNonNumericPartError(err error) bool {
return err != nil && strings.Contains(err.Error(), "parseVersion: parsing") && !strings.Contains(err.Error(), "wrong number of parts")
} Try / catch
v, err := mkversion.InfoFrom(dir)
if err != nil {
if isNonNumericPartError(err) {
return fmt.Errorf("strip 'v' prefix and suffixes from the version string: %w", err)
}
return err
} Prevention
- Never pass git tags verbatim; strip the leading 'v'
- Use `echo ${TAG#v}` style normalization in release scripts
When it happens
Trigger: TS_VERSION_OVERRIDE=v1.72.0; VERSION.txt written as '1.72.x' or '1..0'; any part containing non-digits.
Common situations: Copying git tags (which carry the 'v') into override variables; hand-edited VERSION.txt files.
Related errors
- parseVersion: parsing %q: wrong number of parts: %d
- no module path in go.mod
- failed to parse TS_VERSION_OVERRIDE: %w
- cannot use and advertise exit node at same time
- missing Confirm callback in Arguments
AI-assisted analysis of tailscale/tailscale@6e0912f979 (2026-08-18).
Data as JSON: /api/errors/3e9bfadf4037137d.
Report an issue: GitHub.