Two independent failures on Go 1.27, both pre-existing on main
Verified twice, by two agents working separately, each confirming on a pristine worktree at HEAD with zero changes — so neither is caused by any in-flight work. Both disappear under Go 1.26.3, which go.mod and .github/workflows/gate.yml pin.
1. lint — golangci-lint panics on the Go 1.27 stdlib
golangci-lint v2.12.2 (the version the Makefile pins) bundles staticcheck honnef.co/go/tools v0.7.0, whose IR builder panics while analysing the standard library, not this repo:
buildir: panic during analysis: unexpected expr: *ast.KeyValueExpr (package "poll")
fact_purity: interface conversion: interface {} is nil, not *buildir.IR
-> can't run linter goanalysis_metalinter
It cascades to fact_purity, nilness, typedness and SA5012, and fails the target before it examines a single line of repo code.
2. coverage — one test pins a Go 1.26 JSON escape
compilers/openapi/internal/annotation, TestRawFromNode_DiffersFromTheOldDecodeOnlyWhereRecorded, subtests !!binary /w== and {when: 2021-1-1, blob: !!binary /w==}. Go 1.27's encoding/json emits the raw U+FFFD byte where the expectation pins the escaped form.
Why file it rather than shrug
The Makefile says make gate is what CI runs, and that property is the reason it can be trusted. On a machine with a current Go toolchain it is not true today: the gate fails for reasons that have nothing to do with the change under test, which is exactly the situation that trains people to ignore a red gate.
The workaround is GOTOOLCHAIN=go1.26.3 make gate, which works and is what I used. But nothing in the repo says so, and a contributor hits the panic first.
Suggested
- Pin the toolchain in the
Makefile the way the linter version is already pinned, so make gate reproduces CI without an env var — the Makefile's own comment argues for exactly this discipline about GOLANGCI_LINT_VERSION.
- Then bump Go and golangci-lint together, deliberately, with the escape-pinning test updated in the same change.
Found while working on the spaceapi IR-consumer gaps (#420, #421, #423, #424), 2026-09-05.
Two independent failures on Go 1.27, both pre-existing on
mainVerified twice, by two agents working separately, each confirming on a pristine worktree at HEAD with zero changes — so neither is caused by any in-flight work. Both disappear under Go 1.26.3, which
go.modand.github/workflows/gate.ymlpin.1.
lint— golangci-lint panics on the Go 1.27 stdlibgolangci-lint v2.12.2 (the version the
Makefilepins) bundles staticcheck honnef.co/go/tools v0.7.0, whose IR builder panics while analysing the standard library, not this repo:It cascades to fact_purity, nilness, typedness and SA5012, and fails the target before it examines a single line of repo code.
2.
coverage— one test pins a Go 1.26 JSON escapecompilers/openapi/internal/annotation,TestRawFromNode_DiffersFromTheOldDecodeOnlyWhereRecorded, subtests!!binary /w==and{when: 2021-1-1, blob: !!binary /w==}. Go 1.27'sencoding/jsonemits the raw U+FFFD byte where the expectation pins the escaped form.Why file it rather than shrug
The
Makefilesaysmake gateis what CI runs, and that property is the reason it can be trusted. On a machine with a current Go toolchain it is not true today: the gate fails for reasons that have nothing to do with the change under test, which is exactly the situation that trains people to ignore a red gate.The workaround is
GOTOOLCHAIN=go1.26.3 make gate, which works and is what I used. But nothing in the repo says so, and a contributor hits the panic first.Suggested
Makefilethe way the linter version is already pinned, somake gatereproduces CI without an env var — theMakefile's own comment argues for exactly this discipline aboutGOLANGCI_LINT_VERSION.Found while working on the spaceapi IR-consumer gaps (#420, #421, #423, #424), 2026-09-05.