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
- cmd/go: improve error message for unparsable, too-new, go.mod #70979 (closed)
- cmd/go: go toolchain version switch doesn't work when only language version is set in go.mod #65580 (closed)
- cmd/go: `go env GOMOD` tries to download newer toolchain #61455 (closed)
- cmd/go: some documentation issues for new 1.24 'go tool' features #71663
- cmd/go: using go get go@{version} in a module without a go directive can print a misleading "downgraded" message #63507
- cmd/go: go directive is insufficiently documented for module authors to be able to make a decision about its value #30791 (closed)
- cmd/go: on malformed "go mod edit -go", suggest current version of go, not hardcoded 1.12 #32286 (closed)
- Should the `go` directive in `go.mod` a semver version (including patch), or not? #68971 (closed)
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?