Go 1.26 Changed go mod init — And Nobody Asked For It
A “conservative” default that silently breaks your build and confuses newcomers.
Update: 2026-03-14
In version 1.26.1, it was reverted to the original form from before 1.26, and this article has expired.
Background
Go 1.26 has a quiet change that immediately sparked community debate. When you run go mod init, the generated go.mod now defaults to go 1.25 — one version behind the toolchain you actually have installed.
Let’s look at the before and after:
# Before Go 1.26
$ go version # go1.26
$ go mod init myapp
$ cat go.mod # go 1.26 ← matches installed version
# After Go 1.26
$ go version # go1.26
$ go mod init myapp
$ cat go.mod # go 1.25 ← one version behindOne number. Enormous confusion.
The Build That Breaks Without Warning
Here’s why developers care. Consider a straightforward program using a Go 1.26 feature:
package main
import "fmt"
func main() {
fmt.Println(new(42)) // valid in Go 1.26
}Run it directly — no problem:
$ go run t.go # Works perfectlyNow initialize a module and build:
$ go mod init t
$ go build
# ./t.go:6:14: new(42) requires go1.26 or later
# (-lang was set to go1.25; check go.mod) # can't workSame code, same machine, same toolchain. The only thing that changed was adding a go.mod. And your build is now broken.
This is the scenario described in GitHub issue #77653, titled “revert go mod init to default to 1.N" — which accumulated significant community support within hours of opening.
Go Team’s Rationale
The change originated from #74748. The reasoning isn’t unreasonable:
“Defaulting to 1.(N-1).0 gives users a better initial value, especially for users who don’t manually update the go directive.”
“Per Go’s release policy, we support the two most recent major releases, so this does not cut off any currently-supported Go toolchain.”
The core logic: A module with go 1.25 can be imported by anyone on Go 1.25 or later. A module defaulting to go 1.26 immediately excludes half the currently-supported user base — before you've written a single line of business logic.
For Go team members who run tip builds and regularly edit their go.modThis tradeoff is invisible. @mvdan, a core Go contributor, acknowledged this honestly:
“I run tip daily and almost always need to manually edit the module after go mod init.”
Fair enough. But that perspective reveals the blind spot.
Why the Community Pushed Back
The objections in #77653 fall into three distinct arguments.
The intuition violation
@seankhliao described the mental model mismatch directly:
“Language features and compat settings are both controlled by the go directive. If I install the latest toolchain but can’t use its features by default, and must manually update the version, that’s a worse default.”
We install Go 1.26 to use Go 1.26. That’s the implied contract. A tool that silently undermines this expectation doesn’t feel “conservative” — it feels broken.
The problem shifted, not solved
The original issue author made a sharp point:
“The default still increases each release cycle, just lagging by one version. The problem isn’t solved — it’s shifted by a small offset.”
The compatibility benefit lasts exactly 6 months — one release cycle. When Go 1.27 ships, your “conservative.” go 1.25 module is now two versions behind, and the advantage evaporates. Six months of marginal compatibility, bought at the cost of permanently confusing every developer who doesn't know to run go mod edit -go=1.26 immediately after init.
The newcomer cost
@dolmen raised the most damaging consequence:
“This is bad for beginners. They won’t understand why they installed the latest Go but can’t use its latest features.”
Experienced developers hit this, search for it, and fix it in five minutes. Beginners doubt themselves — they wonder if they installed Go incorrectly, if there’s a system configuration problem, if their code is wrong. The friction is invisible to power users and costly for everyone else.
The issue author’s response to mvdan cuts to the heart of it:
“Why should 20–50 Go team members benefit at the cost of millions of regular users experiencing confusion?”
What the go Directive Actually Controls
This controversy surfaced how underappreciated the go directive is. It's not just metadata — it simultaneously controls three distinct behaviors:
- Language semantics — whether
new(42),iter.Pull, and other version-gated features are valid - Minimum toolchain requirement — Go versions below this number cannot build the module
- Standard library behavior — some functions return different results or behave differently across versions
Go 1.26’s change decouples “minimum toolchain requirement” from “language features you can use today.” The intent is to make modules more broadly importable. The execution means you must explicitly opt in to using features that your installed toolchain already supports.
There’s an irony worth naming. Go’s toolchain already handles forward compatibility automatically — if your local Go version is too old for a module, Go will download and use the required version. The toolchain is already smart enough to handle this. Artificially lowering the default go directive doesn't provide lasting compatibility; it adds a gotcha at module initialization.
What You Should Do Now
Until this resolves — and community pressure may well lead to a patch revert — the fix is one extra command:
# Initialize then immediately update the go directive
go mod init myapp && go mod edit -go=1.26
# Or edit go.mod directly after creation
# Change: go 1.25
# To: go 1.26If you’re writing a library that genuinely needs to support Go 1.25 users, set go 1.25 explicitly. The difference is that's your deliberate choice — not a default you didn't ask for.
Summary
- The change:
go mod initin Go 1.26 defaults togo 1.25, notgo 1.26 - The impact: Code using Go 1.26 features silently breaks after
go mod init - Go team’s reasoning: Conservative defaults improve module compatibility for N-1 toolchain users
- Community argument: Installed version should equal usable version — until the developer decides otherwise
- The paradox: Go already handles forward compatibility automatically; a “conservative” default adds friction without lasting benefit
- Workaround:
go mod edit -go=1.26immediately aftergo mod init
Good defaults are invisible. They match what users expect without requiring documentation. A default that reliably surprises developers isn’t conservative — it’s a paper cut that compounds at scale.