{"record":{"id":"f33c13a0133f96bc","repo":"golang/go","slug":"gomodtoolversion-is-required-for-tool-directive","errorCode":null,"errorMessage":"${GoModToolVersion} is required for tool directives in go.mod: go get go@${GoModToolVersion}.0","messagePattern":"(.+?) is required for tool directives in go\\.mod: go get go@(.+?)\\.0","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/cmd/go/internal/modload/init.go","lineNumber":1963,"sourceCode":"\t\t\twroteGo = true\n\t\t\tforceGoStmt(modFile, mainModule, goVersion)\n\t\t}\n\t}\n\n\t// Add Go 1.24 requirement if we're running go get and there are tool directives.\n\ttools := map[string]bool{}\n\tfor _, t := range modFile.Tool {\n\t\ttools[t.Path] = true\n\t}\n\tfor _, t := range opts.DropTools {\n\t\tdelete(tools, t)\n\t}\n\tfor _, t := range opts.AddTools {\n\t\ttools[t] = true\n\t}\n\tif len(tools) > 0 && gover.Compare(goVersion, gover.GoModToolVersion) < 0 && cfg.CmdName == \"get\" {\n\t\tif opts.ExplicitToolchain {\n\t\t\treturn nil, nil, nil, errors.New(gover.GoModToolVersion + \" is required for tool directives in go.mod: go get go@\" + gover.GoModToolVersion + \".0\")\n\t\t}\n\t\t// TODO: If we start enforcing that the go version is > 1.24 on modules\n\t\t// that have tool directives, add a requirement instead of calling forceGoStmt.\n\t\tgoVersion = gover.GoModToolVersion\n\t\tforceGoStmt(modFile, mainModule, gover.GoModToolVersion)\n\t}\n\n\tif toolchain == \"\" {\n\t\ttoolchain = \"go\" + goVersion\n\t}\n\ttoolVers := gover.FromToolchain(toolchain)\n\tif opts.DropToolchain || toolchain == \"go\"+goVersion || (gover.Compare(toolVers, gover.GoStrictVersion) < 0 && !opts.ExplicitToolchain) {\n\t\t// go get toolchain@none or toolchain matches go line or isn't valid; drop it.\n\t\t// TODO(#57001): 'go get' should reject explicit toolchains below GoStrictVersion.\n\t\tmodFile.DropToolchainStmt()\n\t} else {\n\t\tmodFile.AddToolchainStmt(toolchain)\n\t}","sourceCodeStart":1945,"sourceCodeEnd":1981,"githubUrl":"https://github.com/golang/go/blob/b6b368adc57c96c3151d224d172029f233ead2c3/src/cmd/go/internal/modload/init.go#L1945-L1981","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Run `go get go@<GoModToolVersion>.0` (e.g. go@1.24.0) to raise the go directive to the required floor.","Remove the explicit toolchain pin so the go command can auto-upgrade the go directive.","Drop the tool directive(s) from go.mod if the tool isn't actually needed."],"exampleFix":"// before\n// go.mod:\n//   go 1.23.0\n//   tool (\n//     golang.org/x/tools/cmd/goimports\n//   )\n// running: GOFLAGS=-toolchain=go1.23.0 go get -tool golang.org/x/tools/cmd/goimports\n\n// after\n//   go get go@1.24.0   # bumps the `go` directive, clears the error","handlingStrategy":"validation","validationCode":"// Before running `go get` with tool directives, ensure the go directive is high enough.\nimport \"os/exec\"\n\nfunc ensureGoVersionForTools() error {\n    out, err := exec.Command(\"go\", \"env\", \"GOVERSION\").Output()\n    if err != nil { return err }\n    // GoModToolVersion floor (1.24 for the tool-directive feature).\n    if !strings.Contains(string(out), \"go1.24\") &&\n       !strings.HasPrefix(strings.TrimSpace(string(out)), \"go1.2\") {\n        return fmt.Errorf(\"bump go directive first: go get go@1.24.0\")\n    }\n    return nil\n}","typeGuard":"null","tryCatchPattern":"null","preventionTips":["Keep the `go` directive at the toolchain floor (>= GoModToolVersion) in any module using tool directives.","Avoid pinning an explicit toolchain in CI unless you also bump the go directive.","When adding a tool directive, immediately run `go get go@<floor>.0` in the same change."],"tags":["go-mod","toolchain","go-get","versioning","tool-directive"],"analyzedSha":"b6b368adc57c96c3151d224d172029f233ead2c3","analyzedAt":"2026-08-12T00:22:02.250Z","schemaVersion":2},"datasetVersion":"2026-08-12T12:17:08.281Z"}