JuliusBrussee/caveman · warning · ErrBudgetExceeded
ccr typed object put: %w
Error message
ccr typed object put: %w
What it means
Returned when putting a typed object into the CCR store would push total storage past the configured maxBytes cap. It wraps the sentinel ErrBudgetExceeded, so callers can detect it with errors.Is. The check subtracts the bytes of any existing row with the same object_id (a re-put replaces, not adds) before comparing against the budget.
Source
Thrown at engine/ccr/store_sqlite.go:513
return "", err
}
deps, err := json.Marshal(obj.Dependencies)
if err != nil {
return "", fmt.Errorf("ccr typed object dependencies: %w", err)
}
used, err := s.storageBytes()
if err != nil {
return "", fmt.Errorf("ccr typed object budget: %w", err)
}
var existingBytes int64
err = s.db.QueryRow(`SELECT length(data)+length(dependencies_json) FROM typed_objects WHERE object_id=?`, obj.ID).Scan(&existingBytes)
if errors.Is(err, sql.ErrNoRows) {
existingBytes = 0
} else if err != nil {
return "", fmt.Errorf("ccr typed object budget: %w", err)
}
if used-existingBytes+int64(len(obj.Data)+len(deps)) > s.maxBytes {
return "", fmt.Errorf("ccr typed object put: %w", ErrBudgetExceeded)
}
result, err := s.db.Exec(
`INSERT INTO typed_objects (
object_id, object_type, content_hash, source, created_at, repository_state,
session_id, transform_version, currentness, lifecycle, dependencies_json,
original_byte_length, stored_byte_length, data
) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?)
ON CONFLICT(object_id) DO NOTHING`,
obj.ID, obj.Type, obj.ContentHash, obj.Source, obj.CreatedAt.Format(time.RFC3339Nano),
obj.RepositoryState, obj.SessionID, obj.TransformVersion, obj.Currentness,
obj.Lifecycle, string(deps), obj.OriginalByteLength, obj.StoredByteLength, obj.Data,
)
if err != nil {
if isFull(err) {
return "", fmt.Errorf("ccr typed object put: %w", ErrBudgetExceeded)
}
return "", fmt.Errorf("ccr typed object put: %w", err)
}View on GitHub (pinned to 27d5a3981a)
Solutions
- Treat this as an operational, non-fatal condition: the engine falls back to pass-through, so usually no action is needed beyond alerting.
- Increase the store's maxBytes configuration if compression hit-rate matters for your workload.
- Add eviction/GC of old typed_objects so used bytes stay under the cap.
- If a single object exceeds maxBytes, chunk or exclude that artifact type from the store.
Example fix
// before: treating any put error as fatal
if _, err := store.PutTypedObject(ctx, obj); err != nil { return err }
// after: recognize the sentinel and continue without CCR
if _, err := store.PutTypedObject(ctx, obj); err != nil {
if errors.Is(err, ccr.ErrBudgetExceeded) { /* skip caching, keep going */ } else { return err }
} Defensive patterns
Strategy: try-catch
Type guard
func isBudgetExceeded(err error) bool { return errors.Is(err, ccr.ErrBudgetExceeded) } Try / catch
if _, err := store.PutTypedObject(obj); err != nil {
if errors.Is(err, ccr.ErrBudgetExceeded) {
// expected operational condition: skip caching, keep the pipeline running
return nil
}
return err
} Prevention
- Size maxBytes to at least the sum of your largest expected artifacts plus headroom.
- Monitor used-bytes metrics from the store so you see the ceiling approaching.
- Evict stale typed_objects periodically instead of letting the store only grow.
When it happens
Trigger: PutTypedObject with obj.Data + dependencies_json large enough that used - existingBytes + newBytes > s.maxBytes; typically after the cache has accumulated entries near the cap, or a single very large object exceeds the whole budget.
Common situations: Long-lived cache that never evicts hitting its configured ceiling; maxBytes set too small for the workload's artifact sizes; a burst of large typed objects (e.g. big embedded blobs) filling the store.
Related errors
- ccr: recovery handle not found
- ccr: storage budget exceeded
- cave_harness_aborted
- cave_breaker_retry_requires_budget
- cave_breaker_retry_spend_invalid
AI-assisted analysis of JuliusBrussee/caveman@27d5a3981a (2026-08-15).
Data as JSON: /api/errors/b69f71c8f0979cc0.
Report an issue: GitHub.