JuliusBrussee/caveman · error
read sqlite journal mode
Error message
read sqlite journal mode: %w
What it means
This error wraps a failure to read back the current journal mode via sqliteJournalMode (PRAGMA journal_mode) after configuring it. The store reads the mode to detect filesystems that silently ignore the WAL request; if the read itself fails the open is aborted and the db closed.
Solutions
- Check for competing processes/locks on the database file and retry after they exit
- Run 'sqlite3 <path> "PRAGMA journal_mode;"' to verify the database is readable at all
- If the file is corrupted, restore from backup or delete and let the store recreate it
- Retry open with the store's RetryOnBusy semantics satisfied (ensure busy_timeout is applied)
Example fix
// before
store, err := ccr.Open(dbPath) // fails: read sqlite journal mode
// after
if _, err := os.Stat(dbPath); err == nil {
// verify externally that the db is readable before opening
cmd := exec.Command("sqlite3", dbPath, "PRAGMA journal_mode;")
if err := cmd.Run(); err != nil { /* restore or recreate */ }
}
store, err := ccr.Open(dbPath) Defensive patterns
Strategy: retry
Validate before calling
cmd := exec.Command("sqlite3", dbPath, "PRAGMA journal_mode;")
if err := cmd.Run(); err != nil {
return fmt.Errorf("cannot read journal mode of %s: %w", dbPath, err)
} Try / catch
store, err := ccr.Open(dbPath)
if err != nil && strings.Contains(err.Error(), "read sqlite journal mode") {
// wait for the competing lock holder to exit, then retry
time.Sleep(500 * time.Millisecond)
store, err = ccr.Open(dbPath)
} Prevention
- Ensure single-writer discipline across processes
- Verify db integrity after crashes (PRAGMA integrity_check)
- Retry opens with backoff when other instances may hold locks
When it happens
Trigger: The 'PRAGMA journal_mode' query inside sqliteJournalMode returns an error: locked database, corrupted file, or driver-level failure executing the query.
Common situations: Another process holding an exclusive lock; database file corrupted by a prior crash; unusual filesystems blocking pragma queries.
Understand the failure class
Background: Database query failed: Internal Server Error 500s wrapping SQL, Prisma, and connection failures — what to check first — this error's family across 16 libraries.
Related errors
- configure sqlite journal
- broken supersession history at
- budget is below CCR storage minimum
- cave_ccr_budget_exceeded
- caveman sync requires Node >= 22.13 (it reads the local…
AI-assisted analysis of JuliusBrussee/caveman@3ee70a1026 (2026-09-20).
Data as JSON: /api/errors/23e13130e7027a8a.
Report an issue: GitHub.
Appendix: source
Thrown at engine/ccr/store_sqlite.go:211
// One writer connection. With a single connection every statement serializes
// in-process (no self-contention) while busy_timeout absorbs cross-process
// contention; it is also mandatory for an in-memory DSN, where a second
// pooled connection would be a second, empty database.
db.SetMaxOpenConns(1)
db.SetMaxIdleConns(1)
walJournal := false
if canonicalPath != ":memory:" {
if err := persistSQLiteWAL(db); err != nil {
closeSQLiteAfterOpenFailure(db, canonicalPath)
return nil, fmt.Errorf("configure sqlite journal: %w", err)
}
// A filesystem that cannot back -shm (NFS, SMB, some roaming profiles)
// leaves the DSN's journal_mode request unapplied. Requiring the WAL
// sidecars there would report a perfectly good database as replaced.
mode, err := sqliteJournalMode(db)
if err != nil {
closeSQLiteAfterOpenFailure(db, canonicalPath)
return nil, fmt.Errorf("read sqlite journal mode: %w", err)
}
walJournal = strings.EqualFold(mode, "wal")
}
if err := RetryOnBusy(func() error { _, e := db.Exec(schema); return e }); err != nil {
closeSQLiteAfterOpenFailure(db, canonicalPath)
return nil, fmt.Errorf("migrate sqlite %q: %w", canonicalPath, err)
}
if err := RetryOnBusy(func() error { return ensureMetadataColumn(db) }); err != nil {
closeSQLiteAfterOpenFailure(db, canonicalPath)
return nil, fmt.Errorf("migrate sqlite metadata %q: %w", canonicalPath, err)
}
if err := RetryOnBusy(func() error { return ensureDataRefColumn(db) }); err != nil {
_ = db.Close()
return nil, fmt.Errorf("migrate sqlite data_ref %q: %w", canonicalPath, err)
}
if err := configureStorageBudget(db, maxBytes); err != nil {
closeSQLiteAfterOpenFailure(db, canonicalPath)
return nil, fmt.Errorf("configure sqlite storage budget %q: %w", canonicalPath, err)View on GitHub (pinned to 3ee70a1026)