{"record":{"id":"8604457e79785c08","repo":"benbjohnson/litestream","slug":"write-ltx-from-wal-w","errorCode":null,"errorMessage":"write ltx from wal: %w","messagePattern":"write ltx from wal: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"db.go","lineNumber":2193,"sourceCode":"\t\tif err := db.writeLTXFromDB(ctx, enc, walFile, commit, pageMap); err != nil {\n\t\t\tif isDiskFullError(err) {\n\t\t\t\treturn result, NewLTXError(\"stage-write\", tmpFilename, 0, uint64(txID), uint64(txID), fmt.Errorf(\"%w: %w\", ErrDiskFull, err))\n\t\t\t}\n\t\t\treturn result, fmt.Errorf(\"write ltx from db: %w\", err)\n\t\t}\n\t} else {\n\t\tdb.setSyncDiagPhase(diagPhaseWriteLTXFromWAL,\n\t\t\tfunc(s *diagState) {\n\t\t\t\ts.txID = txID\n\t\t\t\ts.walSize = sz\n\t\t\t\ts.snapshotting = false\n\t\t\t\ts.reason = info.reason\n\t\t\t})\n\t\tif err := db.writeLTXFromWAL(ctx, enc, walFile, info.prevCommit, commit, pageMap); err != nil {\n\t\t\tif isDiskFullError(err) {\n\t\t\t\treturn result, NewLTXError(\"stage-write\", tmpFilename, 0, uint64(txID), uint64(txID), fmt.Errorf(\"%w: %w\", ErrDiskFull, err))\n\t\t\t}\n\t\t\treturn result, fmt.Errorf(\"write ltx from wal: %w\", err)\n\t\t}\n\t}\n\n\t// Encode final trailer to the end of the LTX file.\n\tdb.setSyncDiagPhase(diagPhaseCloseLTX, func(s *diagState) {\n\t\ts.txID = txID\n\t\ts.walSize = sz\n\t})\n\tif err := enc.Close(); err != nil {\n\t\tif isDiskFullError(err) {\n\t\t\treturn result, NewLTXError(\"stage-write\", tmpFilename, 0, uint64(txID), uint64(txID), fmt.Errorf(\"%w: %w\", ErrDiskFull, err))\n\t\t}\n\t\treturn result, fmt.Errorf(\"close ltx encoder: %w\", err)\n\t}\n\n\t// Sync & close LTX file.\n\tdb.setSyncDiagPhase(diagPhaseFsyncLTX, func(s *diagState) {\n\t\ts.txID = txID","sourceCodeStart":2175,"sourceCodeEnd":2211,"githubUrl":"https://github.com/benbjohnson/litestream/blob/4ed7a308f6271ebfd2b0a6e4b70b03011a37e4a3/db.go#L2175-L2211","documentation":"db.writeLTXFromWAL failed with a non-disk-full error while copying WAL frames into the incremental LTX file. This is the incremental replication path: frames are read from the WAL file and encoded as page data; any read/encode failure other than ENOSPC aborts the sync for this transaction.","triggerScenarios":"WAL file truncated, rotated, or replaced mid-read (salt/frame mismatch with rd.salt1/salt2 captured earlier); read I/O error on the WAL; context cancellation; ltx encoder write failure.","commonSituations":"Another process deleting/rotating the -wal file (e.g. running `sqlite3 db 'PRAGMA wal_checkpoint(TRUNCATE)'` or VACUUM concurrently via a different toolchain); mismatched sqlite library versions; crash-truncated WAL after power loss.","solutions":["Verify no other process manipulates the database's WAL file; let litestream be the only WAL-aware monitor.","Check WAL integrity (sqlite3 integrity_check) and confirm salt mismatch logs; a reset will resnapshot.","Run `litestream reset` for the database to clear local LTX state and force a fresh snapshot.","Check dmesg for storage read errors; retry after transient I/O issues clear.","Make sure the app and litestream use compatible SQLite versions/builds (modernc.org/sqlite per repo guidance)."],"exampleFix":"// before: app cron checkpoints/truncates WAL externally\n*/5 * * * * sqlite3 /data/app.db 'PRAGMA wal_checkpoint(TRUNCATE);'\n// after: remove the cron; rely on litestream-managed sync/checkpointing\n# (deleted cron entry)","handlingStrategy":"try-catch","validationCode":"// ensure WAL exists and is not being rotated externally:\nif _, err := os.Stat(dbPath + \"-wal\"); err != nil {\n    return fmt.Errorf(\"wal missing before sync: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"if err != nil && strings.Contains(err.Error(), \"write ltx from wal\") {\n    log.Printf(\"incremental sync failed: %v; salts may have mismatched — consider litestream reset to resnapshot\", err)\n}","preventionTips":["Never checkpoint/truncate/delete the WAL outside litestream","Let litestream be the sole WAL monitor for the database","Use matched SQLite builds (modernc.org/sqlite) across the stack","Reset and resnapshot after any WAL truncation or power-loss corruption"],"tags":["ltx","wal","io-error","replication"],"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-14T05:17:10.506Z"}