{"record":{"id":"23e13130e7027a8a","repo":"JuliusBrussee/caveman","slug":"read-sqlite-journal-mode-w","errorCode":null,"errorMessage":"read sqlite journal mode: %w","messagePattern":"read sqlite journal mode: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"engine/ccr/store_sqlite.go","lineNumber":211,"sourceCode":"\t// One writer connection. With a single connection every statement serializes\n\t// in-process (no self-contention) while busy_timeout absorbs cross-process\n\t// contention; it is also mandatory for an in-memory DSN, where a second\n\t// pooled connection would be a second, empty database.\n\tdb.SetMaxOpenConns(1)\n\tdb.SetMaxIdleConns(1)\n\twalJournal := false\n\tif canonicalPath != \":memory:\" {\n\t\tif err := persistSQLiteWAL(db); err != nil {\n\t\t\tcloseSQLiteAfterOpenFailure(db, canonicalPath)\n\t\t\treturn nil, fmt.Errorf(\"configure sqlite journal: %w\", err)\n\t\t}\n\t\t// A filesystem that cannot back -shm (NFS, SMB, some roaming profiles)\n\t\t// leaves the DSN's journal_mode request unapplied. Requiring the WAL\n\t\t// sidecars there would report a perfectly good database as replaced.\n\t\tmode, err := sqliteJournalMode(db)\n\t\tif err != nil {\n\t\t\tcloseSQLiteAfterOpenFailure(db, canonicalPath)\n\t\t\treturn nil, fmt.Errorf(\"read sqlite journal mode: %w\", err)\n\t\t}\n\t\twalJournal = strings.EqualFold(mode, \"wal\")\n\t}\n\tif err := RetryOnBusy(func() error { _, e := db.Exec(schema); return e }); err != nil {\n\t\tcloseSQLiteAfterOpenFailure(db, canonicalPath)\n\t\treturn nil, fmt.Errorf(\"migrate sqlite %q: %w\", canonicalPath, err)\n\t}\n\tif err := RetryOnBusy(func() error { return ensureMetadataColumn(db) }); err != nil {\n\t\tcloseSQLiteAfterOpenFailure(db, canonicalPath)\n\t\treturn nil, fmt.Errorf(\"migrate sqlite metadata %q: %w\", canonicalPath, err)\n\t}\n\tif err := RetryOnBusy(func() error { return ensureDataRefColumn(db) }); err != nil {\n\t\t_ = db.Close()\n\t\treturn nil, fmt.Errorf(\"migrate sqlite data_ref %q: %w\", canonicalPath, err)\n\t}\n\tif err := configureStorageBudget(db, maxBytes); err != nil {\n\t\tcloseSQLiteAfterOpenFailure(db, canonicalPath)\n\t\treturn nil, fmt.Errorf(\"configure sqlite storage budget %q: %w\", canonicalPath, err)","sourceCodeStart":193,"sourceCodeEnd":229,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/3ee70a102609e550bd2e68004bf5990a9341c851/engine/ccr/store_sqlite.go#L193-L229","documentation":"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.","triggerScenarios":"The 'PRAGMA journal_mode' query inside sqliteJournalMode returns an error: locked database, corrupted file, or driver-level failure executing the query.","commonSituations":"Another process holding an exclusive lock; database file corrupted by a prior crash; unusual filesystems blocking pragma queries.","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)"],"exampleFix":"// before\nstore, err := ccr.Open(dbPath) // fails: read sqlite journal mode\n// after\nif _, err := os.Stat(dbPath); err == nil {\n    // verify externally that the db is readable before opening\n    cmd := exec.Command(\"sqlite3\", dbPath, \"PRAGMA journal_mode;\")\n    if err := cmd.Run(); err != nil { /* restore or recreate */ }\n}\nstore, err := ccr.Open(dbPath)","handlingStrategy":"retry","validationCode":"cmd := exec.Command(\"sqlite3\", dbPath, \"PRAGMA journal_mode;\")\nif err := cmd.Run(); err != nil {\n    return fmt.Errorf(\"cannot read journal mode of %s: %w\", dbPath, err)\n}","typeGuard":null,"tryCatchPattern":"store, err := ccr.Open(dbPath)\nif err != nil && strings.Contains(err.Error(), \"read sqlite journal mode\") {\n    // wait for the competing lock holder to exit, then retry\n    time.Sleep(500 * time.Millisecond)\n    store, err = ccr.Open(dbPath)\n}","preventionTips":["Ensure single-writer discipline across processes","Verify db integrity after crashes (PRAGMA integrity_check)","Retry opens with backoff when other instances may hold locks"],"tags":["sqlite","journal-mode","pragma"],"backgroundTag":"database-query-failed","analyzedSha":"3ee70a102609e550bd2e68004bf5990a9341c851","analyzedAt":"2026-09-20T15:53:39.229Z","contentChangedAt":"2026-09-20T15:53:39.229Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}