JuliusBrussee/caveman · critical
: inspect database
Error message
%w: inspect database%s: %v
What it means
The main database file (path + "" suffix) disappeared while its identity was being inspected. Because the main DB file must always exist for a valid store, ErrNotExist on it is treated as proof the storage changed — ErrStorageChanged is returned. In checkGeneration this error latches terminal quarantine: the Store is unusable for the rest of the process.
Solutions
- Restore the database file at the original path (from backup) or let a fresh process recreate it: stop the process, then reopen.
- Do not try to reuse the current Store — quarantine is latched; instantiate a new Store via Open/OpenWithBudget after the file situation is fixed.
- Exclude the store directory from cleanup tools (bleachbit, tmpwatch, cron rm jobs).
- If the database was deliberately moved, update the store path configuration and restart.
- Check for concurrent processes deleting/racing on the same ccr.db path and serialize them.
Example fix
// before
store.Put(rec) // ccr.db deleted underneath -> quarantined
// after
if _, err := os.Stat(dbPath); err != nil {
store.Close()
store, _ = ccr.Open(dbPath)
}
store.Put(rec) Defensive patterns
Strategy: try-catch
Validate before calling
if _, err := os.Stat(dbPath); err != nil {
// db missing: reopen fresh before calling the store
store.Close(); store, _ = ccr.Open(dbPath)
} Try / catch
if errors.Is(err, ccr.ErrStorageChanged) {
// quarantine is terminal: replace the Store
store, _ = ccr.Open(dbPath) // new process-level store
} Prevention
- Exclude the store directory from disk-cleanup jobs (tmpwatch, cron rm)
- Do not delete/recreate ccr.db under a running process
- Restore databases only while the engine is stopped
- Monitor for parallel processes sharing the same store path
When it happens
Trigger: The .db file itself (not -wal/-shm, which may legitimately be absent) is missing when a Store method runs or when OpenWithBudget inspects before opening — deleted by a cleanup tool, replaced by a rename, or removed while the connection stayed open.
Common situations: Disk cleanup deletes ~/.caveman/ccr.db while the agent runs; a deployment script recreates the database file; the file was moved to another volume; the process was resumed from a snapshot where the file no longer exists.
Understand the failure class
Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.
Related errors
- : database or journal removed or replaced; connection…
- : refusing non-regular database
- budget is below CCR storage minimum
- cave_ccr_budget_exceeded
- ccr storage budget is below minimum
AI-assisted analysis of JuliusBrussee/caveman@3ee70a1026 (2026-09-20).
Data as JSON: /api/errors/f32a06980980d9fd.
Report an issue: GitHub.
Appendix: source
Thrown at engine/ccr/store_generation.go:64
return files, fmt.Errorf("%w: database parent changed", ErrStorageChanged)
}
info, err := os.Stat(parent)
if errors.Is(err, os.ErrNotExist) {
return files, fmt.Errorf("%w: database parent changed", ErrStorageChanged)
}
if err != nil {
return files, fmt.Errorf("%w: %w: inspect database parent: %v", ErrStorageChanged, errStorageUnverifiable, err)
}
if err := validateSQLiteParentSecurity(parent, info); err != nil {
return files, fmt.Errorf("%w: %w: %v", ErrStorageChanged, errStorageUnverifiable, err)
}
for i, suffix := range sqliteSuffixes {
info, err := inspectSQLiteFile(path + suffix)
if errors.Is(err, os.ErrNotExist) && i != 0 {
continue
}
if errors.Is(err, os.ErrNotExist) {
return files, fmt.Errorf("%w: inspect database%s: %v", ErrStorageChanged, suffix, err)
}
if err != nil {
return files, fmt.Errorf("%w: %w: inspect database%s: %v", ErrStorageChanged, errStorageUnverifiable, suffix, err)
}
if !info.Mode().IsRegular() {
return files, fmt.Errorf("%w: refusing non-regular database%s", ErrStorageChanged, suffix)
}
files[i] = info
}
return files, nil
}
func sameSQLiteFile(a, b os.FileInfo) bool {
if a == nil || b == nil {
return a == nil && b == nil
}
return os.SameFile(a, b)
}View on GitHub (pinned to 3ee70a1026)