JuliusBrussee/caveman · error
CAVEMAN_CCR_MAX_BYTES must be a positive integer
Error message
CAVEMAN_CCR_MAX_BYTES must be a positive integer
What it means
The CAVEMAN_CCR_MAX_BYTES environment variable was set but could not be parsed as a positive 64-bit integer, or parsed to a value <= 0. Open rejects the configuration up front rather than falling back to a default, so a bad env var fails loudly instead of silently changing the budget.
Solutions
- Set CAVEMAN_CCR_MAX_BYTES to a plain positive integer of bytes, e.g. 104857600 for 100 MiB.
- Unset the variable entirely to use DefaultMaxStorageBytes if you did not intend to override the budget.
- Remove unit suffixes, underscores, thousands separators, and surrounding quotes from the value.
- Convert human sizes before export: 50MB -> 52428800.
- Check the deployment config/secret for placeholder values like "<max-bytes>" or "changeme".
Example fix
# before export CAVEMAN_CCR_MAX_BYTES=100MB # after export CAVEMAN_CCR_MAX_BYTES=104857600
Defensive patterns
Strategy: validation
Validate before calling
raw := strings.TrimSpace(os.Getenv("CAVEMAN_CCR_MAX_BYTES"))
if raw != "" {
if n, err := strconv.ParseInt(raw, 10, 64); err != nil || n <= 0 {
return fmt.Errorf("CAVEMAN_CCR_MAX_BYTES must be a positive integer, got %q", raw)
}
} Prevention
- Always set the variable as plain decimal bytes, no unit suffixes
- Unset the variable rather than setting 0 when you want the default
- Validate deployment env/secrets at startup with a fail-fast preflight
- Document accepted format (int64 > 0) next to the config key
When it happens
Trigger: ccr.Open(path) is called with CAVEMAN_CCR_MAX_BYTES set to something like "abc", "", after TrimSpace it is non-empty but non-numeric (e.g. "10MB", "1_000"), negative ("-5"), or zero ("0"), or a value above int64 range ("99999999999999999999").
Common situations: Operator writes a human-readable size like "100MB" instead of raw bytes; quotes or whitespace/unit suffixes copied from docs; value 0 intended to mean 'unlimited'; CI secrets misconfigured with a placeholder string.
Understand the failure class
Background: "is not a valid" / "Invalid ... value" environment variable errors: how libraries validate env vars and what to do when they reject yours — this error's family across 48 libraries.
Related errors
- ccr max storage bytes must be positive
- compat upstream name
- githubapp: app id is required
- kms: unsupported provider
- provider upstream URL scheme is not allowed
AI-assisted analysis of JuliusBrussee/caveman@3ee70a1026 (2026-09-20).
Data as JSON: /api/errors/3c1087b6a3b33f3b.
Report an issue: GitHub.
Appendix: source
Thrown at engine/ccr/store_sqlite.go:143
return err
}
func isBusy(err error) bool {
if err == nil {
return false
}
s := err.Error()
return strings.Contains(s, "database is locked") || strings.Contains(s, "SQLITE_BUSY")
}
// Open opens (creating if needed) the SQLite database at path and migrates the
// schema. Use ":memory:" for an ephemeral store (tests, the eval harness).
func Open(path string) (*Store, error) {
maxBytes := DefaultMaxStorageBytes
if raw := strings.TrimSpace(os.Getenv("CAVEMAN_CCR_MAX_BYTES")); raw != "" {
parsed, err := strconv.ParseInt(raw, 10, 64)
if err != nil || parsed <= 0 {
return nil, fmt.Errorf("CAVEMAN_CCR_MAX_BYTES must be a positive integer")
}
maxBytes = parsed
}
return OpenWithBudget(path, maxBytes)
}
// OpenWithBudget opens a persistent store with an explicit retained-payload
// budget. New writes fail with ErrBudgetExceeded; existing recovery rows are
// never evicted because an emitted transformed request may still reference any
// handle.
func OpenWithBudget(path string, maxBytes int64) (*Store, error) {
return openWithBudget(path, maxBytes, nil)
}
func openWithBudget(path string, maxBytes int64, afterPrepare func()) (*Store, error) {
return openWithBudgetHooks(path, maxBytes, afterPrepare, nil)
}
View on GitHub (pinned to 3ee70a1026)