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

  1. Upgrade your installed Go to at least the version named in the failing module's go.mod.
  2. Allow automatic toolchain switching: unset GOTOOLCHAIN or set GOTOOLCHAIN=auto (default) so go fetches the required version.
  3. Pin the toolchain in your own go.mod via a `toolchain go1.23.0` line so all contributors and CI use the same version.
  4. 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

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


AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12). Data as JSON: /api/errors/9bf3a66480955766. Report an issue: GitHub.