golang/go · error · entryNotFoundError
incomplete ProgResponse OutputID
Error message
incomplete ProgResponse OutputID
What it means
The GOCACHEPROG program returned an OutputID byte slice whose length doesn't match the expected hash size (32 bytes for SHA-256). The code copies res.OutputID into the fixed-size OutputID array and checks whether all bytes were copied. If copy returns fewer bytes than len(res.OutputID), the response's OutputID is shorter than HashSize, meaning the program sent a truncated or wrong-length hash.
Source
Thrown at src/cmd/go/internal/cache/prog.go:293
if err != nil {
return Entry{}, err // TODO(bradfitz): or entryNotFoundError? Audit callers.
}
if res.Miss {
return Entry{}, &entryNotFoundError{}
}
e := Entry{
Size: res.Size,
}
if res.Time != nil {
e.Time = *res.Time
} else {
e.Time = time.Now()
}
if res.DiskPath == "" {
return Entry{}, &entryNotFoundError{errors.New("GOCACHEPROG didn't populate DiskPath on get hit")}
}
if copy(e.OutputID[:], res.OutputID) != len(res.OutputID) {
return Entry{}, &entryNotFoundError{errors.New("incomplete ProgResponse OutputID")}
}
c.noteOutputFile(e.OutputID, res.DiskPath)
return e, nil
}
func (c *ProgCache) noteOutputFile(o OutputID, diskPath string) {
c.mu.Lock()
defer c.mu.Unlock()
c.outputFile[o] = diskPath
}
func (c *ProgCache) OutputFile(o OutputID) string {
c.mu.Lock()
defer c.mu.Unlock()
return c.outputFile[o]
}
func (c *ProgCache) Put(a ActionID, file io.ReadSeeker) (_ OutputID, size int64, _ error) {View on GitHub (pinned to b6b368adc5)
Solutions
- Fix the GOCACHEPROG program to return a 32-byte SHA-256 OutputID in every hit response
- Ensure the cache program uses SHA-256 (not MD5, SHA-1, or another algorithm) to match the Go toolchain
- Update the cache program to match the Go version's cacheprog protocol specification
- Temporarily unset GOCACHEPROG to use the default disk cache
- Add logging in the cache program to verify the OutputID length before sending responses
Example fix
// before: GOCACHEPROG returns wrong-length OutputID
// (in the cache program's Get handler)
// return &Response{Miss: false, DiskPath: path, OutputID: md5hash} // 16 bytes!
// after: use SHA-256 to produce 32-byte OutputID
// hash := sha256.Sum256(outputData)
// return &Response{
// Miss: false,
// DiskPath: path,
// OutputID: hash[:], // exactly 32 bytes
// Size: int64(len(outputData)),
// } Defensive patterns
Strategy: validation
Validate before calling
// Verify the GOCACHEPROG program returns 32-byte SHA-256 OutputIDs. // This can be tested by performing a Put followed by a Get and checking // the OutputID length in the response. // // SHA-256 produces 32 bytes. The Go toolchain expects exactly this. // If the program uses a different hash, it must be fixed.
Type guard
func isIncompleteOutputID(err error) bool {
return err != nil && strings.Contains(err.Error(), "incomplete ProgResponse OutputID")
} Try / catch
// entry, err := progCache.Get(id)
// if err != nil {
// if isIncompleteOutputID(err) {
// // The cache program returned a wrong-length OutputID.
// // Fall back to disk cache.
// os.Unsetenv("GOCACHEPROG")
// entry, err = diskCache.Get(id)
// }
// if err != nil {
// output = rebuild()
// }
// } Prevention
- Verify the cache program uses SHA-256 (32 bytes) for OutputID — not MD5 (16) or SHA-1 (20)
- Test the program with a round-trip Put+Get before production use
- Review the cacheprog protocol specification (cmd/internal/cacheprog) the program implements
- Keep the program updated to match your Go version
- Add a response validation step in the cache program before sending
When it happens
Trigger: ProgCache.Get() calls copy(e.OutputID[:], res.OutputID) and the return value (bytes copied into the [32]byte array) != len(res.OutputID). This means len(res.OutputID) > 32 and the array couldn't hold it, or the copy was incomplete.
Common situations: The GOCACHEPROG program returns a truncated hash (e.g., 16 bytes instead of 32); protocol version mismatch where the program uses a different hash algorithm or size; bug in the cache program's response construction where OutputID is nil or empty on a hit.
Related errors
- GOCACHEPROG didn't populate DiskPath on get hit
- GOCACHEPROG didn't return DiskPath in put response
- GOCACHEPROG program closed unexpectedly
- too long
- file is empty
AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12).
Data as JSON: /api/errors/f54daf4f8d1eb063.
Report an issue: GitHub.