-
Notifications
You must be signed in to change notification settings - Fork 876
make modernize will break on the next Go pkgbits bump #7818
Description
Describe the bug
make modernize has the same latent breakage that go install faillint had, and it will fail CI at the next Go release that increments the export data version.
Makefile:226:
modernize:
GOTOOLCHAIN=auto go run golang.org/x/tools/gopls/internal/analysis/modernize/cmd/modernize@v0.22.0 -fix ./...go run pkg@version resolves the target's go.mod, not ours. So the x/tools that modernize is built against is whatever gopls v0.22.0 pins, regardless of what our module graph requires. It is pinned, not maintained by us, and coupled to the Go toolchain version with nothing recording that coupling.
The mechanism is the one described in #7815: the Go compiler writes type information at a pkgbits version, and an analysis tool whose x/tools is older than that version cannot decode it. Go 1.24 through 1.26 all wrote V2; Go 1.27 writes V4. A tool pinned to an x/tools that predates V4 fails with internal error: package "..." without types was imported from "...".
Why it is not broken right now
gopls v0.22.0 requires golang.org/x/tools v0.44.1-0.20260513175300-635ae9663724 (verified from gopls/go.mod at tag gopls/v0.22.0). That pseudo-version is dated 2026年05月13日, which postdates both V4 support (x/tools v0.44.0) and the corrected unified reader (CL 765504, released in v0.45.0). So it decodes Go 1.27 output correctly.
That is luck, not design. The pin happens to be recent enough. Nothing ties it to the FROM golang: version in build-image/Dockerfile.
To Reproduce
Not reproducible today, which is the point. It becomes reproducible on the first Go release that writes pkgbits V5 or later:
- Bump
build-image/Dockerfileto that Go version. - Run
make modernize(ormake check-modernize). - It fails with
internal error: package "..." without types was imported from "...".
The same shape is reproducible now on Go 1.27 with a pre-V4 x/tools, using faillint as the stand-in tool, in golang:1.27.0-trixie:
$ go install github.com/fatih/faillint@v1.15.0 # pins x/tools v0.30.0, max V2
$ faillint -paths "sync/atomic=go.uber.org/atomic" ./...
faillint: internal error: package "net/http" without types was imported from "chk"
$ echo $?
1
Expected behavior
A Go toolchain bump should not be able to silently break a lint tool, and if it does, the failure should point at the thing that needs changing.
Impact
check-modernize runs in CI (.github/workflows/test-build-deploy.yml:42), so this fails the lint job. As with faillint, the failure will not surface in the PR that causes it: build-image/** is excluded from that workflow via paths-ignore, so it lands on whichever unrelated PR next bumps LATEST_BUILD_IMAGE_TAG.
Environment
Build and CI tooling, not a runtime issue. Affects make modernize, make check-modernize and the lint CI job.
Additional Context
Candidate fixes, in rough order of preference. None are verified yet:
- Declare modernize as a
tooldependency, so MVS picks x/tools from our own module graph, as proposed for faillint in Build faillint from the main module instead ofgo install#7816 . Open question: the command lives undergopls/internal/..., and it is not clear whethergo get -toolaccepts a path inside aninternalsubtree. That needs checking before assuming this works. - Bump the pin and document the coupling, noting in the
Makefilethat the pin must move whenever theFROM golang:line inbuild-image/Dockerfilemoves. Cheapest, but relies on someone reading a comment across a gap of potentially years. - Drop the version and use
@latest, which removes the coupling at the cost of reproducible builds. Inconsistent with how every other tool in the repo is pinned.
The two cases differ in one respect worth noting: gopls is actively maintained, so a newer pin is always available. faillint has had no commit since 2025-03, which is why the module-graph approach mattered more there.
I only searched the Makefile for other instances of this pattern. Any go run or go install of an x/tools-based analysis tool at a pinned version has it; faillint and modernize are the only two occurrences I found.
AI usage disclosure, per GENAI_POLICY.md: this issue was drafted with AI assistance (Claude Code). The factual claims were verified before filing: Makefile:226 and test-build-deploy.yml:42 read from the tree; the gopls v0.22.0 x/tools requirement read from gopls/go.mod at tag gopls/v0.22.0; the failure output reproduced in golang:1.27.0-trixie. The candidate fixes are explicitly marked unverified.