golang/go · error
file content changed underfoot
Error message
file content changed underfoot
What it means
Raised while committing a cache output file: the writer reads the final byte, hashes the content, and compares to the expected OutputID before writing the byte that completes the expected size. A mismatch means the file was altered between the initial write and the commit — another process or external actor changed it. The cache truncates and returns this error to avoid publishing a corrupt entry.
Source
Thrown at src/cmd/go/internal/cache/cache.go:690
h := sha256.New()
w := io.MultiWriter(f, h)
if _, err := io.CopyN(w, file, size-1); err != nil {
f.Truncate(0)
return err
}
// Check last byte before writing it; writing it will make the size match
// what other processes expect to find and might cause them to start
// using the file.
buf := make([]byte, 1)
if _, err := file.Read(buf); err != nil {
f.Truncate(0)
return err
}
h.Write(buf)
sum := h.Sum(nil)
if !bytes.Equal(sum, out[:]) {
f.Truncate(0)
return fmt.Errorf("file content changed underfoot")
}
// Commit cache file entry.
if _, err := f.Write(buf); err != nil {
f.Truncate(0)
return err
}
if err := f.Close(); err != nil {
// Data might not have been written,
// but file may look like it is the right size.
// To be extra careful, remove cached file.
os.Remove(name)
return err
}
os.Chtimes(name, c.now(), c.now()) // mainly for tests
return nil
}View on GitHub (pinned to b6b368adc5)
Solutions
- Keep GOCACHE on a local per-machine filesystem; never share it across hosts.
- Give each machine/container its own GOCACHE directory.
- Run `go clean -cache` to flush possibly-corrupt entries and rebuild.
- Disable any process that scans/alters files under GOCACHE.
Example fix
// before: shared cache on a network FS // GOCACHE=/mnt/nfs/shared-go-build -> file content changed underfoot // // after: per-machine local cache $ GOCACHE=$HOME/.cache/go-build go build .
Defensive patterns
Strategy: fallback
Try / catch
err := c.PutOutput(...)
if err != nil && strings.Contains(err.Error(), "file content changed underfoot") {
// shared/unsafe GOCACHE: fall back to a clean rebuild
_ = os.RemoveAll(c.Dir)
// retry the build without parallel cache writers Prevention
- Never put GOCACHE on a network filesystem shared across hosts.
- Give each machine/container a unique local cache.
- Exclude GOCACHE from backup/antivirus scans.
When it happens
Trigger: Concurrent writers to the same cache entry racing on the same output ID; external modification of cache files between write and verify; unreliable shared filesystem (NFS/network FS) semantics. The package doc explicitly warns cross-machine sharing is unsafe.
Common situations: GOCACHE on a network mount shared across machines/containers; two go invocations racing on the same GOCACHE on a filesystem with weak locking; backup/AV scanners touching cache files.
Related errors
- inode for file changed since last Lock or RLock
- not a directory
- %s %s: missing ziphash: %v
- failed to create cache directory: %w
- error: size of %s changed during reading (from %d to %d byte
AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12).
Data as JSON: /api/errors/aae7ab49ae5ca22d.
Report an issue: GitHub.