{"record":{"id":"3972bd6973d2e62a","repo":"benbjohnson/litestream","slug":"get-database-position-w","errorCode":null,"errorMessage":"get database position: %w","messagePattern":"get database position: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"db.go","lineNumber":1593,"sourceCode":"\tif fi, err := os.Stat(db.WALPath()); err == nil && fi.Size() >= WALHeaderSize {\n\t\treturn nil\n\t}\n\n\t// Otherwise create transaction that updates the internal litestream table.\n\treturn db.bumpLitestreamSeq(ctx)\n}\n\n// checkDatabaseBehindReplica detects when a database has been restored to an\n// earlier state and the replica has a higher TXID. This handles issue #781.\n//\n// If detected, it clears local L0 files and fetches the latest L0 LTX file\n// from the replica to establish a baseline. The next DB.sync() will detect\n// the mismatch and trigger a snapshot at the current database state.\nfunc (db *DB) checkDatabaseBehindReplica(ctx context.Context) error {\n\t// Get database position from local L0 files\n\tdbPos, err := db.Pos()\n\tif err != nil {\n\t\treturn fmt.Errorf(\"get database position: %w\", err)\n\t}\n\n\t// Get replica position from remote\n\treplicaInfo, err := db.Replica.MaxLTXFileInfo(ctx, 0)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"get replica position: %w\", err)\n\t} else if replicaInfo.MaxTXID == 0 {\n\t\treturn nil // No remote replica data yet\n\t}\n\n\t// Check if database is behind replica\n\tif dbPos.TXID >= replicaInfo.MaxTXID {\n\t\treturn nil // Database is ahead or equal\n\t}\n\n\tdb.Logger.Info(\"detected database behind replica\",\n\t\t\"db_txid\", dbPos.TXID,\n\t\t\"replica_txid\", replicaInfo.MaxTXID)","sourceCodeStart":1575,"sourceCodeEnd":1611,"githubUrl":"https://github.com/benbjohnson/litestream/blob/4ed7a308f6271ebfd2b0a6e4b70b03011a37e4a3/db.go#L1575-L1611","documentation":"Litestream's checkDatabaseBehindReplica compares the local database position (derived from local L0 LTX files) against the remote replica position. This error wraps any failure from db.Pos(), which scans local LTX state to compute the current TXID. It means Litestream could not determine the local transaction position, so it cannot safely check whether the database is behind its replica.","triggerScenarios":"db.sync() (or the periodic sync/check path) invokes checkDatabaseBehindReplica and db.Pos() fails — e.g. the database's LTX directory is unreadable, corrupt L0 files exist, or the position cache is invalid and re-deriving the position fails.","commonSituations":"Corrupted or partially-written LTX files under the DB's LTX directory (disk full, crash mid-write); wrong db path/cdirectory permissions after moving the data dir; running litestream against a directory whose L0 files were manually deleted or edited; filesystem I/O errors on the volume hosting the database.","solutions":["Check filesystem health and permissions on the DB's LTX directory (ls -l, df -h); fix disk-full or permission problems.","Run `litestream ltx -level 0` (or inspect the LTX dir) to find corrupt/unreadable LTX files.","If local LTX state is corrupt, run `litestream reset` for the database to clear local LTX state and re-snapshot from the replica.","Inspect the wrapped cause (%w) in logs — the underlying os/stat error names the exact file or path that failed."],"exampleFix":"// before: silent confusion about why position fails\nlog.Println(\"sync failed\")\n// after: log the wrapped cause to find the offending file\nlog.Printf(\"sync failed: %v\", err) // e.g. \"get database position: open .../ltx/0/...: permission denied\"","handlingStrategy":"try-catch","validationCode":"// Check local LTX dir is readable before running\nif _, err := os.ReadDir(dbPath + \"/ltx/0\"); err != nil {\n    return fmt.Errorf(\"local L0 dir unreadable: %w\", err)\n}","typeGuard":"// Go has no runtime type guard; verify the underlying error\nvar pe *os.PathError\nif errors.As(err, &pe) { log.Printf(\"path %s failed: %v\", pe.Path, pe.Err) }","tryCatchPattern":"if err := db.SyncAndWait(ctx); err != nil {\n    if strings.Contains(err.Error(), \"get database position\") {\n        log.Printf(\"local LTX state unreadable, consider `litestream reset`: %v\", err)\n    }\n}","preventionTips":["Run litestream as a user with read/write on the DB and LTX directories","Monitor disk space on the data volume","Do not manually edit or delete files under the ltx/ directory","Use `litestream reset` instead of hand-cleaning corrupt LTX state"],"tags":["litestream","ltx","filesystem","position"],"backgroundTag":"file-read-failed","analyzedSha":"4ed7a308f6271ebfd2b0a6e4b70b03011a37e4a3","analyzedAt":"2026-09-06T18:29:25.564Z","contentChangedAt":"2026-09-06T18:29:25.564Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}