golang/go · error · entryNotFoundError
too long
Error message
too long
What it means
The Go build cache stores each cache entry as a fixed-size metadata file (~175 bytes) with a version-prefixed header ('v1 ...'). DiskCache.get() allocates a buffer of entrySize+1 bytes and uses io.ReadFull to detect files longer than the expected format. If the read returns more than entrySize bytes, the entry file is larger than the known format, indicating corruption or version incompatibility.
Source
Thrown at src/cmd/go/internal/cache/cache.go:212
type Entry struct {
OutputID OutputID
Size int64
Time time.Time // when added to cache
}
// get is Get but does not respect verify mode, so that Put can use it.
func (c *DiskCache) get(id ActionID) (Entry, error) {
missing := func(reason error) (Entry, error) {
return Entry{}, &entryNotFoundError{Err: reason}
}
f, err := os.Open(c.fileName(id, "a"))
if err != nil {
return missing(err)
}
defer f.Close()
entry := make([]byte, entrySize+1) // +1 to detect whether f is too long
if n, err := io.ReadFull(f, entry); n > entrySize {
return missing(errors.New("too long"))
} else if err != io.ErrUnexpectedEOF {
if err == io.EOF {
return missing(errors.New("file is empty"))
}
return missing(err)
} else if n < entrySize {
return missing(errors.New("entry file incomplete"))
}
if 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' {
return missing(errors.New("invalid header"))
}
eid, entry := entry[3:3+hexSize], entry[3+hexSize:]
eout, entry := entry[1:1+hexSize], entry[1+hexSize:]
esize, entry := entry[1:1+20], entry[1+20:]
etime, entry := entry[1:1+20], entry[1+20:]
var buf [HashSize]byte
if _, err := hex.Decode(buf[:], eid); err != nil {
return missing(fmt.Errorf("decoding ID: %v", err))View on GitHub (pinned to b6b368adc5)
Solutions
- Run go clean -cache to delete and rebuild the entire cache
- Ensure all builds sharing a GOCACHE directory use the same Go version
- Move GOCACHE off network/shared storage to a local path
- Verify filesystem integrity with fsck or equivalent disk diagnostics
Example fix
// before: shared GOCACHE across Go versions causes format mismatch
// $ GOCACHE=/shared/cache go build ./...
// after: use separate cache per Go version
// $ GOCACHE=/tmp/go-cache-$(go version | awk '{print $3}') go build ./...
// or simply clean and rebuild
// $ go clean -cache && go build ./... Defensive patterns
Strategy: try-catch
Validate before calling
// Before relying on cache entries, verify the cache directory health
import "os"
func cacheHealthy(cacheDir string) bool {
info, err := os.Stat(cacheDir)
if err != nil || !info.IsDir() {
return false
}
// Try writing and reading a test file
testFile := filepath.Join(cacheDir, ".healthcheck")
if err := os.WriteFile(testFile, []byte("ok"), 0644); err != nil {
return false
}
os.Remove(testFile)
return true
} Type guard
// entryNotFoundError is the error type wrapping all cache read failures.
// All errors 80-89 are wrapped in *entryNotFoundError via the missing() closure.
// Since entryNotFoundError is unexported, use errors.As with the exported interface.
import "errors"
func isCacheMiss(err error) bool {
// entryNotFoundError.Error() starts with "cache entry not found"
// It also implements Unwrap() so the inner error is accessible
var target interface{ Unwrap() error }
// In practice, Go toolchain internals use a local check:
// errors.Is(err, errMissing) or type assertion on *entryNotFoundError
return err != nil && strings.HasPrefix(err.Error(), "cache entry not found")
} Try / catch
// All cache read errors (80-89) are wrapped in *entryNotFoundError.
// The canonical pattern (used internally by the Go toolchain) is:
entry, err := cache.Get(actionID)
if err != nil {
// Treat ANY cache error as a miss — rebuild the output
// The error message contains the specific reason (too long, file is empty, etc.)
// but for recovery purposes, all should be handled identically: rebuild.
output = rebuildOutput()
} else {
useCachedEntry(entry)
} Prevention
- Run go clean -cache after upgrading Go versions to avoid format mismatches
- Never share a GOCACHE directory across machines or Go versions
- Ensure the cache directory is on reliable local storage, not network mounts
- Monitor disk space — a full disk causes truncated cache writes
- Avoid hard-killing builds (kill -9) which can leave corrupt cache entries
When it happens
Trigger: DiskCache.get(id) is invoked when looking up any cache entry (via Get, GetFile, GetBytes, GetMmap), and the 'a' (action) file on disk contains at least entrySize+1 bytes — io.ReadFull successfully fills the entire entrySize+1 buffer.
Common situations: A newer Go toolchain version changed the cache entry format; cache directory shared across machines or CI runners with different Go versions; disk corruption or filesystem errors extending the file; antivirus or backup software modifying cache files.
Related errors
AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12).
Data as JSON: /api/errors/ab17c2647455b8d0.
Report an issue: GitHub.