JuliusBrussee/caveman · error
retained corpus byte limit %d exceeded
Error message
retained corpus byte limit %d exceeded
What it means
The byte budget for retained corpus data is exhausted: corpusRowRetainedBytes(row) exceeds limits.MaxRetainedBytes minus what has already been accumulated. This bounds total memory held by the corpus, independent of the per-row and session-count caps.
Source
Thrown at cacheengine/cachebench/corpus.go:400
if message.Role == "tool" && message.ToolCallID == "" {
return errors.New("tool message requires tool_call_id")
}
return nil
}
func appendCorpusRow(rows *[]CorpusRow, sessions map[string]bool, retainedBytes *int64, row CorpusRow, limits CorpusLimits) error {
if len(*rows) >= limits.MaxRows {
return fmt.Errorf("row limit %d exceeded", limits.MaxRows)
}
if !sessions[row.SessionID] {
if len(sessions) >= limits.MaxSessions {
return fmt.Errorf("session limit %d exceeded", limits.MaxSessions)
}
sessions[row.SessionID] = true
}
rowBytes := corpusRowRetainedBytes(row)
if rowBytes > limits.MaxRetainedBytes-*retainedBytes {
return fmt.Errorf("retained corpus byte limit %d exceeded", limits.MaxRetainedBytes)
}
*retainedBytes += rowBytes
*rows = append(*rows, row)
return nil
}
func corpusRetainedBytes(rows []CorpusRow) int64 {
var total int64
for _, row := range rows {
total += corpusRowRetainedBytes(row)
}
return total
}
func corpusRowRetainedBytes(row CorpusRow) int64 {
total := int64(len(row.SessionID) + len(row.Model))
for _, message := range row.Input {
total += int64(len(message.Role) + len(message.Content) + len(message.ToolCallID) + len(message.Name))View on GitHub (pinned to 27d5a3981a)
Solutions
- Raise CorpusLimits.MaxRetainedBytes to fit the corpus's total retained size.
- Trim oversized messages in the corpus (shorten large tool outputs) before loading.
- Reduce MaxRows so the row cap binds before the byte cap.
- Shard the corpus and evaluate shards in separate runs.
Example fix
// before limits.MaxRetainedBytes = 256 << 20 // after limits.MaxRetainedBytes = 2 << 30
Defensive patterns
Strategy: validation
Validate before calling
// Estimate retained bytes from file size as a lower bound before loading:
func budgetCheck(path string, limits CorpusLimits) error {
st, err := os.Stat(path)
if err != nil {
return err
}
if st.Size() > limits.MaxRetainedBytes {
return fmt.Errorf("file size %d already exceeds MaxRetainedBytes %d", st.Size(), limits.MaxRetainedBytes)
}
return nil
} Prevention
- Size MaxRetainedBytes from the corpus file size plus overhead, not guesswork.
- Scale MaxRetainedBytes whenever MaxRows is raised.
- Strip huge tool outputs from corpora before benchmarking.
When it happens
Trigger: Cumulative retained bytes across already-appended rows plus the incoming row's retained size would exceed CorpusLimits.MaxRetainedBytes during appendCorpusRow.
Common situations: Loading a corpus with very large message contents (long system prompts, big tool payloads) under a default memory budget; raising MaxRows without proportionally raising MaxRetainedBytes.
Related errors
- cachebench: provider population exceeds 1024
- row limit %d exceeded
- cachebench: nil corpus reader
- message exceeds byte limit
- tool message requires tool_call_id
AI-assisted analysis of JuliusBrussee/caveman@27d5a3981a (2026-08-15).
Data as JSON: /api/errors/2ab9ebf5c5398684.
Report an issue: GitHub.