{"record":{"id":"aae7ab49ae5ca22d","repo":"golang/go","slug":"file-content-changed-underfoot","errorCode":null,"errorMessage":"file content changed underfoot","messagePattern":"file content changed underfoot","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/cmd/go/internal/cache/cache.go","lineNumber":690,"sourceCode":"\th := sha256.New()\n\tw := io.MultiWriter(f, h)\n\tif _, err := io.CopyN(w, file, size-1); err != nil {\n\t\tf.Truncate(0)\n\t\treturn err\n\t}\n\t// Check last byte before writing it; writing it will make the size match\n\t// what other processes expect to find and might cause them to start\n\t// using the file.\n\tbuf := make([]byte, 1)\n\tif _, err := file.Read(buf); err != nil {\n\t\tf.Truncate(0)\n\t\treturn err\n\t}\n\th.Write(buf)\n\tsum := h.Sum(nil)\n\tif !bytes.Equal(sum, out[:]) {\n\t\tf.Truncate(0)\n\t\treturn fmt.Errorf(\"file content changed underfoot\")\n\t}\n\n\t// Commit cache file entry.\n\tif _, err := f.Write(buf); err != nil {\n\t\tf.Truncate(0)\n\t\treturn err\n\t}\n\tif err := f.Close(); err != nil {\n\t\t// Data might not have been written,\n\t\t// but file may look like it is the right size.\n\t\t// To be extra careful, remove cached file.\n\t\tos.Remove(name)\n\t\treturn err\n\t}\n\tos.Chtimes(name, c.now(), c.now()) // mainly for tests\n\n\treturn nil\n}","sourceCodeStart":672,"sourceCodeEnd":708,"githubUrl":"https://github.com/golang/go/blob/b6b368adc57c96c3151d224d172029f233ead2c3/src/cmd/go/internal/cache/cache.go#L672-L708","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before: shared cache on a network FS\n//   GOCACHE=/mnt/nfs/shared-go-build  -> file content changed underfoot\n//\n// after: per-machine local cache\n$ GOCACHE=$HOME/.cache/go-build go build .","handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"err := c.PutOutput(...)\nif err != nil && strings.Contains(err.Error(), \"file content changed underfoot\") {\n    // shared/unsafe GOCACHE: fall back to a clean rebuild\n    _ = os.RemoveAll(c.Dir)\n    // retry the build without parallel cache writers","preventionTips":["Never put GOCACHE on a network filesystem shared across hosts.","Give each machine/container a unique local cache.","Exclude GOCACHE from backup/antivirus scans."],"tags":["cache","concurrency","filesystem","data-integrity"],"analyzedSha":"b6b368adc57c96c3151d224d172029f233ead2c3","analyzedAt":"2026-08-12T00:22:02.250Z","schemaVersion":2},"datasetVersion":"2026-08-12T08:17:17.861Z"}