{"record":{"id":"8a280338a515f162","repo":"golang/go","slug":"file-is-empty","errorCode":null,"errorMessage":"file is empty","messagePattern":"file is empty","errorType":"exception","errorClass":"entryNotFoundError","httpStatus":null,"severity":"error","filePath":"src/cmd/go/internal/cache/cache.go","lineNumber":215,"sourceCode":"\tTime     time.Time // when added to cache\n}\n\n// get is Get but does not respect verify mode, so that Put can use it.\nfunc (c *DiskCache) get(id ActionID) (Entry, error) {\n\tmissing := func(reason error) (Entry, error) {\n\t\treturn Entry{}, &entryNotFoundError{Err: reason}\n\t}\n\tf, err := os.Open(c.fileName(id, \"a\"))\n\tif err != nil {\n\t\treturn missing(err)\n\t}\n\tdefer f.Close()\n\tentry := make([]byte, entrySize+1) // +1 to detect whether f is too long\n\tif n, err := io.ReadFull(f, entry); n > entrySize {\n\t\treturn missing(errors.New(\"too long\"))\n\t} else if err != io.ErrUnexpectedEOF {\n\t\tif err == io.EOF {\n\t\t\treturn missing(errors.New(\"file is empty\"))\n\t\t}\n\t\treturn missing(err)\n\t} else if n < entrySize {\n\t\treturn missing(errors.New(\"entry file incomplete\"))\n\t}\n\tif entry[0] != 'v' || entry[1] != '1' || entry[2] != ' ' || entry[3+hexSize] != ' ' || entry[3+hexSize+1+hexSize] != ' ' || entry[3+hexSize+1+hexSize+1+20] != ' ' || entry[entrySize-1] != '\\n' {\n\t\treturn missing(errors.New(\"invalid header\"))\n\t}\n\teid, entry := entry[3:3+hexSize], entry[3+hexSize:]\n\teout, entry := entry[1:1+hexSize], entry[1+hexSize:]\n\tesize, entry := entry[1:1+20], entry[1+20:]\n\tetime, entry := entry[1:1+20], entry[1+20:]\n\tvar buf [HashSize]byte\n\tif _, err := hex.Decode(buf[:], eid); err != nil {\n\t\treturn missing(fmt.Errorf(\"decoding ID: %v\", err))\n\t} else if buf != id {\n\t\treturn missing(errors.New(\"mismatched ID\"))\n\t}","sourceCodeStart":197,"sourceCodeEnd":233,"githubUrl":"https://github.com/golang/go/blob/b6b368adc57c96c3151d224d172029f233ead2c3/src/cmd/go/internal/cache/cache.go#L197-L233","documentation":"The entry file exists on disk but io.ReadFull returns io.EOF immediately, meaning zero bytes were read. This indicates the file was created but never properly written — typically from a crash or power loss during a cache write operation. The entry is a zero-byte stub where valid content should be.","triggerScenarios":"DiskCache.get(id) opens the entry file via os.Open and io.ReadFull returns 0 bytes with err == io.EOF (the very first read hit end-of-file).","commonSituations":"System crash or power failure interrupted a cache write; filesystem ran out of space mid-write leaving an empty file; antivirus quarantined a partially written file; concurrent processes racing on the same cache directory causing partial writes.","solutions":["Run go clean -cache to remove corrupt zero-byte entries","Check available disk space on the GOCACHE volume (df -h)","Run filesystem integrity checks (fsck, SMART diagnostics)","Ensure no other process is writing to the same cache directory simultaneously"],"exampleFix":"// before: stale zero-byte cache entries from a crash\n// $ go build ./... # fails with 'cache entry not found: file is empty'\n\n// after: clean cache and rebuild\n// $ go clean -cache && go build ./...\n\n// optionally check disk space first\n// $ df -h $(go env GOCACHE)","handlingStrategy":"try-catch","validationCode":"// Check that the cache directory has sufficient free space\n// and that the disk is writable before builds.\nimport \"syscall\"\n\nfunc checkCacheDiskSpace(cacheDir string, minBytes uint64) error {\n    var stat syscall.Statfs_t\n    if err := syscall.Statfs(cacheDir, &stat); err != nil {\n        return err\n    }\n    free := stat.Bavail * uint64(stat.Bsize)\n    if free < minBytes {\n        return fmt.Errorf(\"cache dir %s has only %d bytes free (need %d)\", cacheDir, free, minBytes)\n    }\n    return nil\n}","typeGuard":"// Same as error 80 — all cache get errors are wrapped in *entryNotFoundError.\n// Check by error message prefix since the type is unexported.\n\nfunc isEmptyCacheEntry(err error) bool {\n    return err != nil && strings.Contains(err.Error(), \"file is empty\")\n}","tryCatchPattern":"// entry, err := cache.Get(id)\n// if err != nil {\n//     // 'file is empty' means a zero-byte entry from a crashed write.\n//     // Treat as cache miss and rebuild.\n//     output = rebuild()\n// }\n\n// For automated recovery, periodically clean stale entries:\n// $ go clean -cache  // full clean\n// or set up a cron to clean old cache files","preventionTips":["Ensure adequate disk space before large builds (cache + output space)","Use UPS or reliable power to prevent crashes during writes","Configure antivirus to exclude the GOCACHE directory from scanning","Run go clean -cache periodically as preventive maintenance"],"tags":["go","build-cache","corruption","disk-cache","filesystem"],"analyzedSha":"b6b368adc57c96c3151d224d172029f233ead2c3","analyzedAt":"2026-08-12T00:22:02.250Z","schemaVersion":2},"datasetVersion":"2026-08-12T06:17:24.410Z"}