{"record":{"id":"bd915b140a8527b5","repo":"benbjohnson/litestream","slug":"cannot-snapshot-after-checkpoint-w","errorCode":null,"errorMessage":"cannot snapshot after checkpoint: %w","messagePattern":"cannot snapshot after checkpoint: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"db.go","lineNumber":2619,"sourceCode":"\t\treturn false, fmt.Errorf(\"_litestream_lock: %w\", err)\n\t}\n\n\t// Copy anything that may have occurred after the checkpoint.\n\tdb.setSyncDiagPhase(diagPhaseCheckpointSnapshotBoundary,\n\t\tfunc(s *diagState) {\n\t\t\ts.checkpointMode = mode\n\t\t\ts.lastSyncedWALOffset = exec.state.lastSyncedWALOffset\n\t\t})\n\tsnapshotInfo := syncInfo{\n\t\toffset:       WALHeaderSize,\n\t\tsalt1:        binary.BigEndian.Uint32(other[16:]),\n\t\tsalt2:        binary.BigEndian.Uint32(other[20:]),\n\t\tsnapshotting: true,\n\t\treason:       \"checkpoint boundary snapshot\",\n\t}\n\tresult, err = db.sync(ctx, true, exec, snapshotInfo, 0)\n\tif err != nil {\n\t\treturn false, fmt.Errorf(\"cannot snapshot after checkpoint: %w\", err)\n\t}\n\texec.applySyncResult(result)\n\n\t// Release write lock before exiting.\n\t// Use rollback() helper for consistency with releaseReadLock() and the\n\t// defer above. See issue #934.\n\tif err := rollback(tx); err != nil {\n\t\treturn false, fmt.Errorf(\"rollback post-checkpoint tx: %w\", err)\n\t}\n\n\texec.state.syncedSinceCheckpoint = false\n\treturn true, nil\n}\n\n// execCheckpoint issues a wal_checkpoint PRAGMA in the given mode and returns\n// the number of frames in the WAL as reported by the checkpoint.\nfunc (db *DB) execCheckpoint(ctx context.Context, mode string) (walFrameN int, err error) {\n\t// Ignore if there is no underlying database.","sourceCodeStart":2601,"sourceCodeEnd":2637,"githubUrl":"https://github.com/benbjohnson/litestream/blob/4ed7a308f6271ebfd2b0a6e4b70b03011a37e4a3/db.go#L2601-L2637","documentation":"While still holding the checkpoint write transaction, Litestream performs a boundary snapshot sync (db.sync with a snapshot WAL read position) to capture everything written up to the checkpoint. Failure of that sync is wrapped with this error and aborts the checkpoint. The replication stream will lack the boundary frames until a later sync succeeds.","triggerScenarios":"db.sync(ctx, true, exec, snapshotInfo, 0) fails during the post-checkpoint boundary snapshot: WAL frame read/checksum failure, LTX file creation failure on the replica backend, or storage client errors (network, auth, permissions).","commonSituations":"S3 credentials expired mid-run or bucket permissions revoked; WAL truncated by an external tool causing frame mismatch; disk full preventing LTX staging.","solutions":["Inspect the wrapped error to see whether it is a WAL read failure or a replica storage write failure.","Validate replica storage credentials and permissions, then retry the sync.","Free disk space if the failure involves staging LTX files locally.","Run 'litestream reset' (or enable auto-recover) if LTX state is corrupt and cannot resync."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"if err := storageCheck(ctx); err != nil { /* verify replica backend auth + reachability before checkpointing */ }","typeGuard":null,"tryCatchPattern":"if err != nil && strings.Contains(err.Error(), \"cannot snapshot after checkpoint\") {\n    // inspect cause: WAL read vs storage write; retry; reset if corrupt\n    logAndRetry(err)\n}","preventionTips":["Use expiring-credential rotation with refresh before expiry.","Monitor disk space for LTX staging.","Verify WAL integrity if external tools touch the database.","Enable auto-recover for unattended resilience."],"tags":["snapshot","checkpoint","sync","replication"],"backgroundTag":"wal-sync-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"}