Skip to content

cmd/go: go get -u && go mod tidy behaves differently starting with Go 1.21.0, leading to unknown directive toolchain errors #62409

@gaby

Description

@gaby

What version of Go are you using (go version)?

$ go version
go version go1.21.0 linux/amd64

Does this issue reproduce with the latest release?

Yes

What operating system and processor architecture are you using (go env)?

go env Output
$ go env
GO111MODULE=''
GOARCH='amd64'
GOBIN=''
GOCACHE='/home/ubuntu/.cache/go-build'
GOENV='/home/ubuntu/.config/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFLAGS=''
GOHOSTARCH='amd64'
GOHOSTOS='linux'
GOINSECURE=''
GOMODCACHE='/home/ubuntu/go/pkg/mod'
GONOPROXY=''
GONOSUMDB=''
GOOS='linux'
GOPATH='/home/ubuntu/go'
GOPRIVATE=''
GOPROXY='https://proxy.golang.org,direct'
GOROOT='/snap/go/10319'
GOSUMDB='sum.golang.org'
GOTMPDIR=''
GOTOOLCHAIN='auto'
GOTOOLDIR='/snap/go/10319/pkg/tool/linux_amd64'
GOVCS=''
GOVERSION='go1.21.0'
GCCGO='gccgo'
GOAMD64='v1'
AR='ar'
CC='gcc'
CXX='g++'
CGO_ENABLED='1'
GOMOD='/home/ubuntu/Desktop/git/fix/contrib/websocket/go.mod'
GOWORK=''
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
PKG_CONFIG='pkg-config'
GOGCCFLAGS='-fPIC -m64 -pthread -Wl,--no-gc-sections -fmessage-length=0 -ffile-prefix-map=/tmp/go-build2504710228=/tmp/go-build -gno-record-gcc-switches'

What did you do?

This is a continuation of #57001

Lets say, I have a library made with Go that supports go version 1.17, 1.18, 1.19, and 1.20.

My go.mod file looks as follow:

module github.com/my/lib

go 1.18

require (
	github.com/some/other/lib v1.0.0
)

Normally when getting updates, you would do go get -u -v then go mod tidy. Since go1.21 running go mod tidy now changes your go.mod file to the following:

module github.com/my/lib

go 1.21

toolchain go1.21.0

require (
	github.com/some/other/lib v1.0.0
)

This a breaking change behavior, given that now if I commit that code? Any previous CI/CD process, or any other developer in the team that's using a different version of go can no longer build/test/run the code because of the toolchain directive.

What did you expect to see?

I expected that running go mod tidy would only cleanup imports and the go.sum file.

What did you see instead?

Running go mod tidy changes the go.mod go version and adds a toolchain directive that's not available in any previous go version.

Suggested solution

There's two possible solutions here:

  • Make go commands use the local install by default instead of auto.
  • The go mod tidy command shouldn't change the version/add a directive to go.mod

Example running with go 1.20.7 in Docker:

root@31579b87a9bd:/data# cat go.mod 
module github.com/my/lib

go 1.21

toolchain go1.21.0

require (
	github.com/some/other/lib v1.0.0
)

root@31579b87a9bd:/data# go mod tidy
go: errors parsing go.mod:
/data/go.mod:5: unknown directive: toolchain
root@31579b87a9bd:/data# go version 
go version go1.20.7 linux/amd64

This bring the question, how can we write libraries that are backward compatible with previous go versions?

Metadata

Metadata

Assignees

No one assigned

    Labels

    FrozenDueToAgeGoCommandcmd/goNeedsInvestigationSomeone must examine and confirm this is a valid issue and not a duplicate of an existing one.WaitingForInfoIssue is not actionable because of missing required information, which needs to be provided.

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions