JuliusBrussee/caveman · error
session limit %d exceeded
Error message
session limit %d exceeded
What it means
A new session ID appeared after the session cap was already reached: appendCorpusRow only registers unseen session IDs, and it refuses when len(sessions) >= limits.MaxSessions. Existing sessions can keep adding rows; only distinct new sessions are blocked.
Source
Thrown at cacheengine/cachebench/corpus.go:394
}
messageBytes += len(call.ID) + len(call.Type) + len(call.Function.Name) + len(call.Function.Arguments)
}
if messageBytes > limits.MaxMessageBytes {
return errors.New("message exceeds byte limit")
}
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 totalView on GitHub (pinned to 27d5a3981a)
Solutions
- Increase CorpusLimits.MaxSessions to the number of distinct session IDs in the file.
- Normalize/merge session IDs before loading if IDs were split artificially.
- Filter the corpus to the sessions you actually want to benchmark.
Example fix
// before limits.MaxSessions = 50 // after limits.MaxSessions = 5_000
Defensive patterns
Strategy: validation
Validate before calling
func countSessions(path string) (int, error) {
f, err := os.Open(path)
if err != nil {
return 0, err
}
defer f.Close()
seen := map[string]bool{}
scanner := bufio.NewScanner(f)
for scanner.Scan() {
var row struct{ SessionID string `json:"session_id"` }
if json.Unmarshal(scanner.Bytes(), &row) == nil && row.SessionID != "" {
seen[row.SessionID] = true
}
}
return len(seen), scanner.Err()
} Prevention
- Pre-count distinct session IDs and set MaxSessions above it.
- Keep session ID format stable across pipeline versions.
- Alert when distinct-session counts jump between corpus revisions.
When it happens
Trigger: A corpus row arrives whose SessionID has not been seen before while limits.MaxSessions distinct sessions are already registered.
Common situations: Replaying a wide fleet capture with many short sessions against limits tuned for a few long sessions; session IDs that change format (e.g. new suffix) after a provider migration, inflating distinct-session counts.
Related errors
- cachebench: provider population exceeds 1024
- cachebench: invalid observation read limits
- cacheengine: stable prefix exceeds configured byte limit
- cacheengine: request exceeds configured byte limit
- row limit %d exceeded
AI-assisted analysis of JuliusBrussee/caveman@27d5a3981a (2026-08-15).
Data as JSON: /api/errors/8296094dd3e91b32.
Report an issue: GitHub.