Safeguard
Developer Tools•

How does Go choose a toolchain, and what is GOTOOLCHAIN?

Since Go 1.21 the go line in go.mod is a minimum and the go command can switch toolchains. Learn GOTOOLCHAIN values and how to keep patch levels current.

Safeguard Security Team
4 min read

Since Go 1.21, the go line in go.mod sets a mandatory minimum version, and the toolchain line suggests one. The GOTOOLCHAIN setting decides whether the go command may switch to a newer toolchain automatically. The default is auto, so a module can pull your build onto a newer, patched Go without you installing anything.

The two lines in go.mod

The Go toolchain documentation explains that the go line is the minimum version needed to use the module. A toolchain older than that refuses to load it. The toolchain line names a suggested toolchain, and if omitted it is implied by the go version. A module's go line must be at least as high as the go line of every module it requires.

Before Go 1.21 the go line was advisory. The page notes that Go 1.19.13 and 1.20.8 were backported to refuse modules declaring Go 1.22 or later.

GOTOOLCHAIN values

ValueBehavior
localAlways run the bundled toolchain
autoShorthand for local plus auto; the default for standard toolchains
pathLike auto, but only searches PATH and never downloads
a version name such as go1.21.0Always run that toolchain, downloading and verifying if needed

The setting is read from the process environment, then the user default set with go env -w, then the go.env file in GOROOT. You can check it with go env GOTOOLCHAIN.

Why this matters for patching

With auto, if go.mod asks for a newer toolchain than the one installed, the go command runs the newer one, using a binary on PATH or downloading it. Downloaded toolchains are modules with the path golang.org/toolchain, honor GOPROXY and are checked against the checksum database.

That is a patching win: a repository that bumps its toolchain line to a fixed patch release gets every developer and CI job onto it on the next build.

It is also a control point. In a locked-down build agent, set GOTOOLCHAIN to local or path so builds fail loudly instead of downloading. Then you update the agent image on purpose.

A practical setup

  1. Commit a go line and a toolchain line that name the patch level you want.
  2. On laptops, leave GOTOOLCHAIN at auto.
  3. On build agents with restricted networks, use path or local and bake the Go version into the image.
  4. Move the toolchain line forward as part of regular dependency updates.

Commands like go get can change these lines for you. For example, go get toolchain@none removes the toolchain line, and go get go@1.25.0 also moves the toolchain line.

Watch for silent switches

When a newly added dependency requires a newer Go, the command prints a notice and switches. That is helpful, but review the resulting go.mod change in the pull request like any other change.

Safeguard's dependency scanning covers Go modules and can show which versions your repositories use. A free scan is at gold.safeguard.sh/scan.

Common mistakes

A few to avoid: leaving build agents on auto when they should not download anything, assuming the installed Go is the one that built your binary, and ignoring toolchain lines that change in a pull request. Print go version in CI logs so the answer is always visible.

Quick check

What is the default GOTOOLCHAIN?

Standard toolchains default to auto, which allows switching to a newer toolchain when go.mod requires one.

Can I stop Go from downloading toolchains?

Yes. Set GOTOOLCHAIN to local, or to path to search PATH only, and the go command will not download.

Sources

Last reviewed: 19 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.