golang/go · error
module requires Go ${p.Module.GoVersion} or later
Error message
module requires Go ${p.Module.GoVersion} or later What it means
Thrown by (*Builder).build in cmd/go/internal/work when the module being compiled declares a `go` directive (e.g. `go 1.23`) newer than the running go toolchain's own version (checked via allowedVersion). This is the toolchain's guard against using language features the binary cannot compile — the go directive is treated as a minimum-required-toolchain contract since Go 1.21.
Source
Thrown at src/cmd/go/internal/work/exec.go:653
if need == 0 {
return nil
}
defer b.flushOutput(a)
defer func() {
if err != nil && b.IsCmdList && b.NeedError && p.Error == nil {
p.Error = &load.PackageError{Err: err}
}
}()
if p.Error != nil {
// Don't try to build anything for packages with errors. There may be a
// problem with the inputs that makes the package unsafe to build.
return p.Error
}
if p.Module != nil && !allowedVersion(p.Module.GoVersion) {
return errors.New("module requires Go " + p.Module.GoVersion + " or later")
}
if err := b.checkDirectives(a); err != nil {
return err
}
if err := sh.Mkdir(a.Objdir); err != nil {
return err
}
// Load cached vet config, but only if that's all we have left
// (need == needVet, not testing just the one bit).
// If we are going to do a full build anyway,
// we're going to regenerate the files in the build action anyway.
if need == needVet {
if err := b.loadCachedVet(a, a.Deps); err == nil {
need &^= needVet
}View on GitHub (pinned to b6b368adc5)
Solutions
- Upgrade your installed Go to at least the version named in the failing module's go.mod.
- Allow automatic toolchain switching: unset GOTOOLCHAIN or set GOTOOLCHAIN=auto (default) so go fetches the required version.
- Pin the toolchain in your own go.mod via a `toolchain go1.23.0` line so all contributors and CI use the same version.
- As a last resort, lower the go directive in go.mod — but only if the code genuinely does not use newer language features, and prefer upgrading instead.
Example fix
# before: go.mod says `go 1.23` but installed go is 1.21 $ go version go version go1.21.0 $ go build ./... # -> module requires Go 1.23 or later # after: enable auto toolchain download $ unset GOTOOLCHAIN $ go build ./... # go downloads go1.23 and re-runs
Defensive patterns
Strategy: validation
Validate before calling
func checkGoVersion(required, installed string) error {
r := strings.Split(required, "."); i := strings.Split(installed, ".")
if len(r) >= 2 && len(i) >= 2 {
if r[0] > i[0] || (r[0] == i[0] && r[1] > i[1]) {
return fmt.Errorf("module needs go%s; you have go%s — upgrade or set GOTOOLCHAIN=auto", required, installed)
}
}
return nil
} Type guard
func toolchainSatisfies(required, installed string) bool {
return checkGoVersion(required, installed) == nil
} Prevention
- Pin the toolchain in go.mod via a `toolchain` directive so all contributors match.
- Leave GOTOOLCHAIN at its default (auto) so go can fetch the required version.
- Upgrade CI Go images promptly when the project's go directive bumps.
When it happens
Trigger: Building a module whose go.mod has e.g. `go 1.23` with an installed go 1.21 toolchain. Pulling a dependency that bumped its go directive. Running an older system go against a freshly generated module (`go mod init` on a newer toolchain, then building on an older one).
Common situations: CI images pinned to an older Go. Local developers on distro-provided Go (often older) building modern modules. A transitive dependency raising its minimum. `GOTOOLCHAIN=local` set explicitly, which disables the automatic toolchain download that would otherwise transparently fix this.
Related errors
- must have SWIG version >= 3.0.6
- incorrect number of packages: want 1, got %d
- %s: argument must be a clean package path
- %s: argument must not be a package in the standard library
- %s: %w
AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12).
Data as JSON: /api/errors/9bf3a66480955766.
Report an issue: GitHub.