JuliusBrussee/caveman · error

configure sqlite journal

Error message

configure sqlite journal: %w

What it means

This error wraps a failure to persist the WAL journal mode on the opened SQLite database (persistSQLiteWAL). The store requires WAL for concurrent readers, and if the journal mode cannot be applied/persisted the open is aborted and the half-opened db is closed. This typically means the underlying Exec setting PRAGMA journal_mode=WAL failed.

Solutions

  1. Check no other process holds a write lock on the database; increase busy_timeout if contention is heavy
  2. Move the database to a local filesystem that supports WAL and -shm sidecar files
  3. Run the PRAGMA journal_mode=WAL manually with the sqlite3 CLI to see the underlying failure
  4. If WAL is impossible in your environment, configure a non-WAL journal mode explicitly if the library supports it

Example fix

// before
rows, err := db.Query("SELECT data FROM ccr") // on NFS, WAL pragma failed at open
// after
// relocate db to local disk:
store, err := ccr.Open("/var/lib/app/ccr.db") // local ext4/apfs volume
Defensive patterns

Strategy: retry

Validate before calling

// verify WAL is supportable before opening
out, err := exec.Command("sqlite3", dbPath, "PRAGMA journal_mode;").Output()
if err != nil {
    return fmt.Errorf("db %s not inspectable: %w", dbPath, err)
}

Try / catch

store, err := ccr.Open(dbPath)
if err != nil && strings.Contains(err.Error(), "configure sqlite journal") {
    // fall back to local disk or retry after lock clears
    time.Sleep(250 * time.Millisecond)
    store, err = ccr.Open(dbPath)
}

Prevention

When it happens

Trigger: persistSQLiteWAL's PRAGMA journal_mode=WAL statement returns an error, e.g. the database is locked by another process beyond busy_timeout, or the file is on a filesystem that rejects the operation.

Common situations: Databases on network mounts (NFS/SMB) where WAL cannot be established; a long-running writer in another process holding the lock; read-only file media.

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


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

Appendix: source

Thrown at engine/ccr/store_sqlite.go:203

		// PrepareSQLitePathCanonical already created the file. Never recreate
		// it if it vanishes between preparation and the driver's open.
		dsn += "&mode=rw"
	}
	db, err := sql.Open("sqlite", dsn)
	if err != nil {
		return nil, fmt.Errorf("open sqlite %q: %w", canonicalPath, err)
	}
	// 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)

View on GitHub (pinned to 3ee70a1026)