Skip to content

The Go module cache is read-only, which is why rm -rf fails on it

Go marks every file in its module cache read-only, so deleting the folder answers permission denied hundreds of times. The two commands that actually work.

5 min read

You go looking for the space, you find ~/go/pkg/mod, it is enormous, and you delete it. The terminal answers permission denied several hundred times and the folder is still there, now half deleted.

Nothing is wrong with your permissions. Go writes every file in the module cache without the write bit, deliberately, so that a build cannot quietly modify a dependency whose checksum it has already verified. rm asks the filesystem, the filesystem says no, and the more it is retried the messier the folder gets.

First, measure the right two folders

There are two separate Go caches and they behave differently. Ask Go where they are rather than assuming, because both move with an environment variable.

go env GOMODCACHE GOCACHE
du -sh "$(go env GOMODCACHE)" "$(go env GOCACHE)"
CacheDefault locationHoldsCost of deleting
Module cache~/go/pkg/modThe source of every module version ever downloadedA redownload for every project
Build cache~/Library/Caches/go-buildCompiled results, keyed by inputOne slow rebuild, then normal

The two commands that work

go clean -modcache    # the downloaded module sources
go clean -cache       # the compiled build cache

Go removes the read-only bit itself, so these succeed where rm does not. Neither touches your projects, and neither needs sudo.

If Go is no longer installed and you just want the folder gone, add the write permission first and then delete it:

chmod -R u+w ~/go/pkg/mod && rm -rf ~/go/pkg/mod

Why it grows the way it does

Two things make the module cache larger than people expect.

  • Every version is kept separately. Upgrading a dependency adds the new version and keeps the old one, because another project on your disk may still be pinned to it. Nothing ever decides a version has aged out.
  • Each module is stored roughly twice. The downloaded zip sits in cache/download, and the extracted source tree sits alongside it under the module path. Both are needed, and both count.
du -sh "$(go env GOMODCACHE)/cache/download"

That second point is why the total is often close to double what a look at the module folders suggests.

How big it actually gets

This one varies more than any other cache on a developer's Mac, because it depends entirely on how many services you build and how many dependency upgrades they have been through. A single machine can hold anything from a few hundred megabytes to tens of gigabytes, and a large cloud provider SDK pulls in a lot on its own.

That is exactly why the du command above is worth running rather than trusting a figure from any page, including this one. Measure it, then decide whether it is worth the redownload.

Do this before the redownload matters

The module cache is shared by every Go project on the machine, so clearing it is a cost paid once by whichever project you build next, not per project. If you are about to work offline, build the projects you care about first, or clear only the build cache, which is rebuilt locally with no network at all.

For the rest of a full disk, the safest order to free 100 GB covers the categories that are usually larger, and what is really inside ~/Library/Caches explains why the Go build cache is only one tenant of a much bigger folder.

Common questions

Why does rm -rf fail on the Go module cache?

Go stores every file in the module cache without write permission, so that a build cannot alter a dependency it has already verified. rm cannot remove read-only files without help, which is why it reports permission denied. Use go clean -modcache, or run chmod -R u+w on the folder first.

Is it safe to run go clean -modcache?

Yes. It only removes downloaded dependency sources, which Go refetches on the next build of any project that needs them. Your own code, and any vendored dependencies inside a project, are untouched.

Where is the Go module cache on a Mac?

At ~/go/pkg/mod by default, and the build cache is at ~/Library/Caches/go-build. Both can be moved, so run go env GOMODCACHE GOCACHE to see where they actually are on your machine.

Read next