{"record":{"id":"4150dbf2b6f9fe07","repo":"benbjohnson/litestream","slug":"read-position-after-sync-w","errorCode":null,"errorMessage":"read position after sync: %w","messagePattern":"read position after sync: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"store.go","lineNumber":460,"sourceCode":"\n\t_, beforeTXID, err := db.MaxLTX()\n\tif err != nil {\n\t\treturn SyncDBResult{}, fmt.Errorf(\"read position before sync: %w\", err)\n\t}\n\n\tif wait {\n\t\tif err := db.SyncAndWait(ctx); err != nil {\n\t\t\treturn SyncDBResult{}, fmt.Errorf(\"sync database: %w\", err)\n\t\t}\n\t} else {\n\t\tif err := db.Sync(ctx); err != nil {\n\t\t\treturn SyncDBResult{}, fmt.Errorf(\"sync database: %w\", err)\n\t\t}\n\t}\n\n\t_, afterTXID, err := db.MaxLTX()\n\tif err != nil {\n\t\treturn SyncDBResult{}, fmt.Errorf(\"read position after sync: %w\", err)\n\t}\n\n\tvar replicatedTXID uint64\n\tif db.Replica != nil {\n\t\treplicatedTXID = uint64(db.Replica.Pos().TXID)\n\t}\n\n\treturn SyncDBResult{\n\t\tTXID:           uint64(afterTXID),\n\t\tReplicatedTXID: replicatedTXID,\n\t\tChanged:        afterTXID > beforeTXID,\n\t}, nil\n}\n\n// FindDB returns the database with the given path.\nfunc (s *Store) FindDB(path string) *DB {\n\ts.mu.Lock()\n\tdefer s.mu.Unlock()","sourceCodeStart":442,"sourceCodeEnd":478,"githubUrl":"https://github.com/benbjohnson/litestream/blob/4ed7a308f6271ebfd2b0a6e4b70b03011a37e4a3/store.go#L442-L478","documentation":"Store.SyncDB failed after a successful sync because db.MaxLTX() could not read the post-sync replication position. Since the sync succeeded, this usually indicates a problem reading local LTX position metadata or an unexpected internal state, not a replication failure. The wrapped error is returned with %w.","triggerScenarios":"SyncDB(ctx, path, wait) completes db.Sync/SyncAndWait successfully, but the subsequent db.MaxLTX() call errors while enumerating local LTX files to compute the after TXID.","commonSituations":"Local LTX metadata corruption, filesystem errors after the sync (disk removed, permissions changed mid-call), or a bug/race where the DB was closed concurrently between sync and position read.","solutions":["Re-run SyncDB; if the before-sync read (store.go:445) also fails, treat it as a local-state problem rather than a sync problem.","Inspect local LTX/replica position files for corruption; run litestream reset to clear corrupted local state for that database.","Check filesystem health and permissions on the Litestream data directory.","Avoid closing/unregistering the DB concurrently with SyncDB calls; serialize lifecycle operations."],"exampleFix":"// before\nres, err := store.SyncDB(ctx, path, true)\n// after\nres, err := store.SyncDB(ctx, path, true)\nif err != nil {\n    // sync may have succeeded; verify position before retrying aggressively\n    log.Printf(\"SyncDB %s: %v\", path, err)\n    return err\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"res, err := store.SyncDB(ctx, path, true)\nif err != nil {\n    // sync may have succeeded; check error position to decide retry\n    log.Printf(\"SyncDB %s failed: %v\", path, err)\n    return err\n}","preventionTips":["Don't close/unregister the DB concurrently with SyncDB","Check local LTX state integrity if this recurs","Log the wrapped error to distinguish position-read vs sync failures","Report persistent failures on healthy DBs as upstream bugs"],"tags":["go","litestream","sync","internal"],"backgroundTag":"internal-invariant-violation","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"}