JuliusBrussee/caveman · error

ccr storage budget is below minimum

Error message

ccr storage budget %d is below minimum %d

What it means

SQLite pages are at least 512 bytes, and CCR requires a minimum page count (minimumStoragePages). openWithBudgetHooks rejects budgets below minimumStoragePages*512 before preparing files or opening a connection, because such a budget can never satisfy the minimum page requirement. The actual (possibly larger) page size is verified later by configureStorageBudget.

Solutions

  1. Raise the budget to at least minimumStoragePages*512 bytes; in practice use a realistic value such as several megabytes (e.g. 16*1024*1024).
  2. Read the minimum from the package if exported, or size the budget at the default (use ccr.Open) for tests.
  3. Check the unit: if your config is in KB/MB, multiply to bytes before calling OpenWithBudget.
  4. If the budget is proportional to a quota, clamp it with Math.Max against the library minimum before opening.
  5. For genuinely constrained environments, use :memory: (no budget floor needed) rather than a too-small disk budget.

Example fix

// before
ccr.OpenWithBudget(path, 1024) // below minimum pages
// after
ccr.OpenWithBudget(path, 16*1024*1024)
Defensive patterns

Strategy: validation

Validate before calling

if maxBytes < 4096 { // conservative floor; use exported minimum when available
    return fmt.Errorf("budget %d below sqlite minimum pages", maxBytes)
}
ccr.OpenWithBudget(path, maxBytes)

Prevention

When it happens

Trigger: OpenWithBudget is called with maxBytes in (0, minimumStoragePages*512) — e.g. budgets like 1024 or 4096 bytes that are positive but too small for the required number of minimum-size SQLite pages.

Common situations: A developer picks a tiny budget for unit tests ('1KB should be enough'); a config typo like 500 instead of 500000; a size unit misread as KB instead of bytes (5 * 1024 for '5KB' intended as 5MB); a proportional budget computed from a small quota.

Understand the failure class

Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.

Related errors


AI-assisted analysis of JuliusBrussee/caveman@3ee70a1026 (2026-09-20). Data as JSON: /api/errors/c59643c77d754309. Report an issue: GitHub.

Appendix: source

Thrown at engine/ccr/store_sqlite.go:170

// 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)
}

func openWithBudgetHooks(path string, maxBytes int64, afterPrepare, afterOpen func()) (*Store, error) {
	if maxBytes <= 0 {
		return nil, fmt.Errorf("ccr max storage bytes must be positive")
	}
	// SQLite pages are at least 512 bytes. Reject budgets that cannot satisfy
	// CCR's minimum page count before preparing files or opening a connection.
	// The actual database page size is checked by configureStorageBudget.
	if maxBytes < minimumStoragePages*512 {
		return nil, fmt.Errorf("ccr storage budget %d is below minimum %d", maxBytes, minimumStoragePages*512)
	}
	canonicalPath, err := PrepareSQLitePathCanonical(path)
	if err != nil {
		return nil, err
	}
	if afterPrepare != nil {
		afterPrepare()
	}
	before, err := inspectSQLiteGeneration(canonicalPath)
	if err != nil {
		return nil, err
	}
	dsn := SQLiteDSN(canonicalPath)
	if canonicalPath != ":memory:" {
		// PrepareSQLitePathCanonical already created the file. Never recreate
		// it if it vanishes between preparation and the driver's open.
		dsn += "&mode=rw"
	}

View on GitHub (pinned to 3ee70a1026)