When a tool is registered in go.mod with go get -tool, ensure that the toolchain requirement is at least 1.24.0 (either via the go directive or via toolchain). If that isn't the case, suggest to the user to upgrade (go mod edit -go=1.24.0).

Rationale

go1.23 (and lower) can't parse go.mod with a tool directive, so they can't be used as toolchain.

Go version

go version go1.24.5 darwin/arm64

Output of go env in your module/workspace:

GO111MODULE=''

What did you do?

$ cat go.mod
module github.com/dolmen-go/goeval

go 1.23.0

require (
    golang.org/x/mod v0.24.0
    golang.org/x/tools v0.31.0
)

require golang.org/x/sync v0.12.0 // indirect

tool github.com/dolmen-go/goeval

What did you see happen?

go1.23.11 fails to parse a go.mod that contains a tool directive without a toolchain directive:

$ go1.23.11 list
go: errors parsing go.mod:
go.mod:12: unknown directive: tool
$ go1.23.11 build
go: errors parsing go.mod:
go.mod:12: unknown directive: tool

https://github.com/dolmen-go/goeval/actions/runs/16493582443/job/46633886516#step:4:7

What did you expect to see?

Either: - go 1.23 to ignore the tool directive - or go 1.24+ go get -tool fails to add the tool and suggests to increase the minimum go version in go.mod (go mod edit -go=1.24.0)

Edit

This issue was initially about the go directive in go.mod, but is now corrected to be about toolchain.

Comment From: gabyhelp

Related Issues

Related Documentation

(Emoji vote if this was helpful or unhelpful; more detailed feedback welcome in this discussion.)

Comment From: dolmen

Also: go mod tidy applied to a go.mod with a tool directive and the go directive below 1.24 should upgrade the go version.

Maybe @golang/command-line would prefer to force an upgrade of the go version once get -tool is used?

Comment From: dolmen

From a deeper look at toolchains documentation and golang.org/x/mod/modfile.ParseLax, it seems to me that the tool directive must be paired with the toolchain because tools are used only when the go.mod is processed as the main module.

So I now think that go get -tool (as well as go mod tidy noticing a tool directive) should force a toolchain upgrade to go1.24.0 (like with a manual go get toolchain@1.24.0) but not care about the go directive (as long as it is equal or above 1.21, for toolchain support).

Comment From: dolmen

Cc: @ConradIrwin

Comment From: gopherbot

Change https://go.dev/cl/690836 mentions this issue: cmd/go: upgrade toolchain to 1.24.0 if go.mod declares a tool

Comment From: dolmen

CL 690836 implements the toolchain upgrade when a tool is found in go.mod (go mod tidy) or added (go get -tool).

Comment From: ConradIrwin

Updating out-of-date toolchains when tools are added seems reasonable to me (though I don't think we should a toolchain directive if there isn't one).

Comment From: dolmen

I have now edited the title and description to mention the toolchain directive instead of go.

Comment From: dolmen

@ConradIrwin wrote:

though I don't think we should a toolchain directive if there isn't one

Adding the toolchain is the right thing to do in order to help the developer to be aware of the impact of adding a tool directive before the code is pushed. The case of the issue being caught by a CI running go1.23.x (ex: GitHub Actions running with oldstable and stable) is already too late.

$ cat go.mod
module x

go 1.23.0
$ cat main.go
package main

func main() {}
$ go1.23.11 list
x
$ go1.24.5 list
x
$ go1.24.5 get -tool .
module x

go 1.23.0

tool x
$ go1.24.5 list
x
$ go1.23.11 list
go: errors parsing go.mod:
go.mod:5: unknown directive: tool

Comment From: matloob

I also don't think upgrading the toolchain directive is correct. We've tied other features to the go directive and we should do the same here.

We should probably just fail if the go directive is below 1.24, and perhaps suggest for the user to run go get go@1.24 to upgrade to 1.24?