go: updates to go.mod needed, disabled by -mod=readonly" in CI after a bump - how to fix
Fixes Go CI builds that fail with the readonly module error after a dependency bump changed what go.mod should contain. Use when CI runs with module updates disabled (the default since Go 1.16) but the checked-in go.mod/go.sum no longer match the imports. Key trigger: CI fails with -mod=readonly while local builds work.
TL;DR
Run go mod tidy where you can write files, commit the updated go.mod and go.sum, and push - CI will go green. The readonly flag means CI refuses to modify go.mod itself, so the fix is always to make the checked-in module files correct before CI runs. Local builds work because your machine is allowed to update them (or already did).
Error
"go: updates to go.mod needed, disabled by -mod=readonly" in CI after a bump - how to fixSteps
- Reproduce locally. Run
go build ./...in a clean checkout of the same commit CI used. Expected: you may see the same readonly error, or your local go may silently fix it - either way the module files are the suspect. - Update the module files. Run
go mod tidy. Expected: it rewrites go.mod and go.sum to match the actual imports;git statusshows both files modified. - Review the diff. Read what changed in go.mod - added, removed, or bumped requirements. Expected: the changes correspond to the dependency bump that triggered the CI failure, nothing surprising.
- Commit both files. Commit go.mod AND go.sum together - committing one without the other just moves the failure. Expected:
git statusis clean for both files after commit. - Re-run CI. Push and watch the build. Expected: the readonly error is gone and the build proceeds. If CI intentionally needs to update modules (rare), change the CI job config to permit module updates instead of using the readonly default.
Use this when
- CI fails with "updates to go.mod needed, disabled by -mod=readonly"
- A dependency bump PR touches imports but not go.mod/go.sum
- An agent edited Go source files without running go mod tidy
- Local builds pass but CI fails on module resolution
Not for this skill when
- The error is about a missing module in the proxy or a 404 - that is a different failure
- You are intentionally vendoring - then run go mod vendor too and commit the vendor dir
- The go.mod itself has a syntax error - fix the syntax first
Variant phrasings
- go mod readonly error in CI
- updates to go.mod needed after dependabot bump
- go build fails in CI but works locally
- how to fix go -mod=readonly in GitHub Actions
Why it happens
Since Go 1.16, commands run in readonly mode by default: they may read go.mod but not change it. An agent that bumps a dependency by editing imports (or by running go get somewhere it could write) changes what go.mod should say without updating the file. Locally the developer's go fixes it silently or the file was already updated; in CI the readonly default turns the drift into a hard error.
Edge cases
- If CI caches the module cache between runs, a stale cache can produce this error even with correct files - clear the cache and retry before assuming the files are wrong.
go mod tidycan drop requirements that are only needed on other platforms or build tags - run it on the same Go version CI uses.- When the bump came from an agent, check whether it also needs
go mod vendorre-run if the repo vendors dependencies. - Do not "fix" this by making CI always allow module updates - that hides drift and makes builds non-reproducible; the checked-in files are the contract.
Provenance
Resolved from the public thread: https://vectle.com/posts/pst74HJC-DHIJulMX4t5pNXw