golang/go · error

${GoModToolVersion} is required for tool directives in go.mo

Error message

${GoModToolVersion} is required for tool directives in go.mod: go get go@${GoModToolVersion}.0

What it means

The go command requires the `go` directive in go.mod to be at least gover.GoModToolVersion when the module declares `tool` directives. During `go get`, if tools are present, the current go version is below that minimum, and the user pinned the toolchain explicitly (opts.ExplicitToolchain), it refuses rather than silently bumping the version. The message tells you exactly how to satisfy the requirement.

Source

Thrown at src/cmd/go/internal/modload/init.go:1963

			wroteGo = true
			forceGoStmt(modFile, mainModule, goVersion)
		}
	}

	// Add Go 1.24 requirement if we're running go get and there are tool directives.
	tools := map[string]bool{}
	for _, t := range modFile.Tool {
		tools[t.Path] = true
	}
	for _, t := range opts.DropTools {
		delete(tools, t)
	}
	for _, t := range opts.AddTools {
		tools[t] = true
	}
	if len(tools) > 0 && gover.Compare(goVersion, gover.GoModToolVersion) < 0 && cfg.CmdName == "get" {
		if opts.ExplicitToolchain {
			return nil, nil, nil, errors.New(gover.GoModToolVersion + " is required for tool directives in go.mod: go get go@" + gover.GoModToolVersion + ".0")
		}
		// TODO: If we start enforcing that the go version is > 1.24 on modules
		// that have tool directives, add a requirement instead of calling forceGoStmt.
		goVersion = gover.GoModToolVersion
		forceGoStmt(modFile, mainModule, gover.GoModToolVersion)
	}

	if toolchain == "" {
		toolchain = "go" + goVersion
	}
	toolVers := gover.FromToolchain(toolchain)
	if opts.DropToolchain || toolchain == "go"+goVersion || (gover.Compare(toolVers, gover.GoStrictVersion) < 0 && !opts.ExplicitToolchain) {
		// go get toolchain@none or toolchain matches go line or isn't valid; drop it.
		// TODO(#57001): 'go get' should reject explicit toolchains below GoStrictVersion.
		modFile.DropToolchainStmt()
	} else {
		modFile.AddToolchainStmt(toolchain)
	}

View on GitHub (pinned to b6b368adc5)

Solutions

  1. Run `go get go@<GoModToolVersion>.0` (e.g. go@1.24.0) to raise the go directive to the required floor.
  2. Remove the explicit toolchain pin so the go command can auto-upgrade the go directive.
  3. Drop the tool directive(s) from go.mod if the tool isn't actually needed.

Example fix

// before
// go.mod:
//   go 1.23.0
//   tool (
//     golang.org/x/tools/cmd/goimports
//   )
// running: GOFLAGS=-toolchain=go1.23.0 go get -tool golang.org/x/tools/cmd/goimports

// after
//   go get go@1.24.0   # bumps the `go` directive, clears the error
Defensive patterns

Strategy: validation

Validate before calling

// Before running `go get` with tool directives, ensure the go directive is high enough.
import "os/exec"

func ensureGoVersionForTools() error {
    out, err := exec.Command("go", "env", "GOVERSION").Output()
    if err != nil { return err }
    // GoModToolVersion floor (1.24 for the tool-directive feature).
    if !strings.Contains(string(out), "go1.24") &&
       !strings.HasPrefix(strings.TrimSpace(string(out)), "go1.2") {
        return fmt.Errorf("bump go directive first: go get go@1.24.0")
    }
    return nil
}

Type guard

null

Try / catch

null

Prevention

When it happens

Trigger: Running `go get` (cfg.CmdName == "get") on a module whose go.mod has `tool(...)` directives, while the `go` directive is older than GoModToolVersion AND an explicit toolchain is set (e.g. `GOFLAGS=-toolchain=...` or a toolchain line the user authored). Without the explicit pin the go command auto-upgrades via forceGoStmt instead of erroring.

Common situations: Adding a tool directive to a module still on go 1.23 or earlier; downgrading the go directive below the tool-directive floor; CI that pins an explicit toolchain to keep builds reproducible.

Related errors


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