golang/go · error
invalid version
Error message
invalid %s version %s
What it means
This error is thrown when resolving a 'go' or 'toolchain' module version and the revision string doesn't pass gover.IsValid validation. After stripping the 'go' prefix (e.g., 'go1.21.0' -> '1.21.0'), the remaining string must be a valid Go version. If it's malformed (e.g., '1.foo', '1.2.x', 'v1.21'), IsValid returns false and this error reports which module path (go or toolchain) and revision caused the failure.
Solutions
- Use standard Go version syntax without the 'v' prefix: 'go get go@1.21.0' not 'go@v1.21.0'.
- Include the full version: '1.21.0' not '1.21' for toolchain requests (language versions are handled separately).
- Check the toolchain directive in go.mod: ensure it reads 'toolchain go1.21.0' with proper version format.
- Validate the version string with 'go version' semantics: major.minor[.patch[.build]] with optional prerelease suffix.
Example fix
# before $ go get toolchain@v1.21.0 # invalid toolchain version v1.21.0 # after: no 'v' prefix, standard Go version $ go get toolchain@go1.21.0 # or simply $ go get go@1.21.0
Defensive patterns
Strategy: validation
Validate before calling
// Validate Go version string before using in toolchain queries
import "golang.org/x/mod/semver"
func validateGoVersion(rev string) error {
v := strings.TrimPrefix(rev, "go")
// Go versions don't use 'v' prefix
if strings.HasPrefix(v, "v") {
return fmt.Errorf("Go version must not have 'v' prefix: %s", rev)
}
// Must match N.N or N.N.N pattern
matched, _ := regexp.MatchString(`^\d+\.\d+(\.\d+)?(-[a-z0-9.]+)?$`, v)
if !matched {
return fmt.Errorf("invalid Go version: %s (expected format like 1.21.0)", rev)
}
return nil
} Try / catch
if strings.Contains(stderr, "invalid ") && strings.Contains(stderr, "version") {
// Extract the invalid version from stderr and suggest the correct format
// Remove 'v' prefix, ensure N.N.N format
} Prevention
- Go versions use '1.21.0' format, not semver 'v1.21.0'
- Always strip 'v' prefix when specifying Go versions
- Validate version strings with gover.IsValid equivalent before passing to toolchain commands
- Use 'go version' to see valid version string format
When it happens
Trigger: When go resolves a 'go@version' or 'toolchain@version' query (via go get go@1.21, GOTOOLCHAIN=go1.21.0+auto, or toolchain directive in go.mod). The revision is stripped of the 'go' prefix and checked with gover.IsValid. Invalid revisions like '1.2-beta' (should be '1.2.0-beta') or 'latest' (not a valid version for this code path) trigger this.
Common situations: A toolchain directive in go.mod specifies a malformed version. GOTOOLCHAIN is set to a non-standard version string. A user types 'go get go@1.foo' or 'go get toolchain@v1.21.0' (the 'v' prefix is invalid for Go versions). Confusion between semver ('v1.2.3') and Go version ('1.2.3') syntax.
Related errors
- go language version is not a toolchain version
- build output already exists and is a directory
- build output already exists and is not an object file
- can't request explicit version
- file URL encodes volume in host field: too few slashes?
AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12).
Data as JSON: /api/errors/0c80d46b3892d8dc.
Report an issue: GitHub.
Appendix: source
Thrown at src/cmd/go/internal/modfetch/toolchain.go:99
versions.List = list
return versions, nil
}
func (r *toolchainRepo) Stat(ctx context.Context, rev string) (*RevInfo, error) {
// Convert rev to DL version and stat that to make sure it exists.
// In theory the go@ versions should be like 1.21.0
// and the toolchain@ versions should be like go1.21.0
// but people will type the wrong one, and so we accept
// both and silently correct it to the standard form.
prefix := ""
v := rev
v = strings.TrimPrefix(v, "go")
if r.path == "toolchain" {
prefix = "go"
}
if !gover.IsValid(v) {
return nil, fmt.Errorf("invalid %s version %s", r.path, rev)
}
// If we're asking about "go" (not "toolchain"), pretend to have
// all earlier Go versions available without network access:
// we will provide those ourselves, at least in GOTOOLCHAIN=auto mode.
if r.path == "go" && gover.Compare(v, gover.Local()) <= 0 {
return &RevInfo{Version: prefix + v}, nil
}
// Similarly, if we're asking about *exactly* the current toolchain,
// we don't need to access the network to know that it exists.
if r.path == "toolchain" && v == gover.Local() {
return &RevInfo{Version: prefix + v}, nil
}
if gover.IsLang(v) {
// We can only use a language (development) version if the current toolchain
// implements that version, and the two checks above have ruled that out.View on GitHub (pinned to b6b368adc5)