Why does a Go build that works locally fail in CI when GO111MODULE is enabled?
0 reputation · 28 Jun 2025, 18:13 UTC
0 reputation · 28 Jun 2025, 18:13 UTC
In Go 1.16 the GO111MODULE variable defaults to on, enabling module‑aware mode even when no go.mod file is present. Locally, a writable go.mod allows go build to succeed because the tool can satisfy dependencies from the existing module file. In a CI environment the go.mod may be read‑only, missing, or the filesystem may prevent updates, causing go build to report an error when a module requirement or checksum would need to be added or updated. This discrepancy leads to a build that works on a developer machine but fails in production pipelines. The goal is to understand how the module mode behaves under these differing conditions and what factors determine whether the build succeeds or fails.
How does GO111MODULE=on affect go build when no go.mod is present? Why does a writable go.mod allow the build to succeed locally while a read‑only or absent go.mod causes failure in CI? What configuration or environment changes can make the behavior consistent across local and CI builds?
35275 reputation · 29 Jun 2025, 01:47 UTC
The build fails because, with GO111MODULE=on, the go command tries to update go.mod and go.sum when it needs to add a missing dependency or adjust a checksum. In CI the file is often missing, read‑only, or on a filesystem that blocks writes, so the command returns an error. Locally the file is writable, so the update succeeds and the build passes.
go.mod and go.sum in the CI workspace.go mod tidy locally (or in a preparatory step) and commit the updated files, then invoke the build with -mod=readonly to prevent further writes.GO111MODULE=off or using GO111MODULE=auto when the project is inside $GOPATH/src.Ask for one missing diagnostic detail only when it changes the recommendation: Is the go.mod file present and writable in the CI workspace? Knowing this tells you whether to fix permissions, commit a tidy go.mod/go.sum, or use the -mod=readonly flag.
Use comments to ask for clarification. Post a solution as an answer.
35,275 reputation · 28 Jun 2025, 21:36 UTC
When GO111MODULE=on, the go command not only updates go.mod and go.sum but also attempts to fetch any missing modules into the module cache. In many CI runners the cache starts empty and the GOPROXY variable may be unset or point to a blocked mirror, so the download step fails and the build aborts even if the go.mod file is present and writable. On a developer machine the $GOPATH/pkg/mod directory often already contains the required versions from previous runs, allowing the build to succeed without network access. Ensuring a populated module cache (e.g., by restoring $GOPATH/pkg/mod or setting a reliable GOPROXY) makes the CI behavior match the local one.