深夜2時のパイプライン失敗コードをプッシュし、ローカルテストもパスして、ようやく寝ようとしたその時、CI/CDパイプラインが赤くなります。ログを確認すると、次のような厄介なエラーに直面します。
go: updates to go.sum needed, disabled by -mod=readonly
このエラーは通常、DockerビルドやCIの実行中に発生します。これは、Goツールチェーンが不足しているチェックサムでgo.sumファイルを更新する必要があるものの、変更が制限されていることを意味します。Go 1.16以降、ビルドの不変性と再現性を確保するために、多くのコマンドがデフォルトで-mod=readonlyに設定されています。
発生原因Goは、go.modとgo.sumが完全に同期していることを期待します。同期コマンドを実行せずに依存関係を追加したり、go.modを手動で編集したりすると、go.sumが古くなります。ローカル環境ではGoがこれを自動的に修正することがありますが、GitHub ActionsやGitLab CIなどのCI環境では、依存関係に対してファイルシステムが読み取り専用として扱われることがよくあります。これにより、セキュリティやビルドの安定性を損なう可能性のある「サイレント」な更新が防止されます。
解決方法### 1. 決定的な解決策:go mod tidy最も一般的な原因は、go.modに記載されている依存関係のエントリがgo.sumファイルに不足していることです。ターミナルを開いて以下を実行してください。
go mod tidy
このコマンドは開発者の強い味方です。インポートに必要なモジュールを追加し、未使用のものを削除します。最も重要なのは、プロジェクトに必要な正確なチェックサムを生成し、モジュールグラフを整理してくれる点です。
2. コミットを忘れずによくある落とし穴です。go.mod tidyを実行してローカルで動作を確認しても、更新されたgo.sumファイルをコミットするのを忘れてしまうことがあります。CIランナーはリポジトリにある情報しか知りません。変更をプッシュしなければ、CIは古い壊れた状態のままビルドを試み、再び失敗します。
git add go.mod go.sum
git commit -m "fix: 依存関係を同期しgo.sumを更新"
git push
3. Dockerビルドの修正DockerのRUN go buildステップでこのエラーが発生する場合は、COPYコマンドを確認してください。go.modをコピーしてもgo.sumを除外していると、Goビルダーはその場で新しいチェックサムファイルを生成しようとして失敗します。代わりに以下のパターンを使用してください。
# Dockerレイヤーのキャッシュを活用するため、まず両方のモジュールファイルをコピーする
COPY go.mod go.sum ./
RUN go mod download
# 次に残りのソースコードをコピーする
COPY . .
RUN go build -o myapp .
これにより、ビルドが始まる前にすべてのチェックサムが存在し、検証されていることが保証されます。また、ダウンロードステップをキャッシュすることで、Dockerビルドを高速に保つことができます。
4. クリーンな再ダウンロードを強制するtidyで解決しない場合は、ローカルキャッシュにチェックサムの不一致がある可能性があります。すべてのモジュールを強制的に再ダウンロードして状態を一致させてみてください。
go mod download
go mod verify
verifyコマンドは、ローカルキャッシュ内の依存関係がgo.sumに期待されるチェックサムと一致するかどうかを確認します。ローカルで成功してもCIで失敗する場合、ローカルのgo.sumに間違いなく問題があります。
プッシュ前に検証するCIが通るかどうか推測するのはやめましょう。ビルドをreadonlyフラグを有効にして実行することで、CI環境の厳格さをローカルでシミュレートできます。
go build -mod=readonly ./...
このコマンドが終了コード0で終了すれば、依存関係は完全に同期されています。パイプラインは正常に動作するはずです。

