{"record":{"id":"2847e164ffa352ae","repo":"benbjohnson/litestream","slug":"decode-database-w-2847e1","errorCode":null,"errorMessage":"decode database: %w","messagePattern":"decode database: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"vfs.go","lineNumber":803,"sourceCode":"\t// Compact and decode using io.Pipe pattern\n\tpr, pw := io.Pipe()\n\tc, err := ltx.NewCompactor(pw, rdrs)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"new ltx compactor: %w\", err)\n\t}\n\tc.HeaderFlags = ltx.HeaderFlagNoChecksum\n\th.compactor = c\n\n\tgo func() {\n\t\t_ = pw.CloseWithError(c.Compact(ctx))\n\t}()\n\n\th.mu.Lock()\n\tdefer h.mu.Unlock()\n\n\tdec := ltx.NewDecoder(pr)\n\tif err := dec.DecodeDatabaseTo(h.file); err != nil {\n\t\treturn fmt.Errorf(\"decode database: %w\", err)\n\t}\n\n\th.txid = infos[len(infos)-1].MaxTXID\n\treturn nil\n}\n\n// CatchUp applies updates from LTX files between fromTXID and toTXID.\nfunc (h *Hydrator) CatchUp(ctx context.Context, fromTXID, toTXID ltx.TXID) error {\n\th.logger.Debug(\"catching up hydration\", \"from\", fromTXID, \"to\", toTXID)\n\n\t// Fetch LTX files from fromTXID+1 to toTXID\n\titr, err := h.client.LTXFiles(ctx, 0, fromTXID+1, false)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"list ltx files for catch-up: %w\", err)\n\t}\n\tdefer itr.Close()\n\n\tfor itr.Next() {","sourceCodeStart":785,"sourceCodeEnd":821,"githubUrl":"https://github.com/benbjohnson/litestream/blob/4ed7a308f6271ebfd2b0a6e4b70b03011a37e4a3/vfs.go#L785-L821","documentation":"After compacting LTX readers through an io.Pipe, Hydrator.Restore decodes the compacted stream directly into the hydration file with dec.DecodeDatabaseTo(h.file). This error wraps any failure while streaming the decoded database: compaction errors propagated through the pipe, checksum verification failures, or write errors on the local hydration file.","triggerScenarios":"Calling Restore where the compacted stream is truncated or its checksums don't match (corrupt replica objects, interrupted download surfaced via pw.CloseWithError), the hydration file's disk is full or unwritable, or page size in the LTX header doesn't match h.pageSize.","commonSituations":"Flaky object storage dropping bytes mid-stream; disk quota exceeded on the node holding the hydration file; replica files corrupted by a partial upload; restoring across litestream versions with differing header flags (HeaderFlagNoChecksum vs checksummed).","solutions":["Inspect the wrapped cause: if it came through the pipe, the real failure is c.Compact's error (upstream read/checksum) — re-fetch or re-verify the replica files.","Check free disk space and write permissions on the directory holding the hydration file; retry after clearing space.","Delete the partial hydration file and re-run Restore from scratch; use `litestream reset` if local LTX state is corrupt.","Confirm the replica's page size matches the local database configuration; a mismatched -page-size between backup and restore causes decode failure."],"exampleFix":"// before\nif err := dec.DecodeDatabaseTo(h.file); err != nil {\n    return fmt.Errorf(\"decode database: %w\", err)\n}\n// after\nif err := dec.DecodeDatabaseTo(h.file); err != nil {\n    _ = h.file.Close()\n    _ = os.Remove(h.path) // drop partial hydration file\n    return fmt.Errorf(\"decode database: %w\", err)\n}","handlingStrategy":"fallback","validationCode":"// verify free space before decoding\nif st, err := os.Stat(filepath.Dir(h.path)); err == nil {\n    _ = st // ensure mount exists and is writable via a probe write\n}","typeGuard":null,"tryCatchPattern":"if err := dec.DecodeDatabaseTo(h.file); err != nil {\n    os.Remove(h.path) // drop partial hydration file\n    return fmt.Errorf(\"decode database: %w\", err)\n}","preventionTips":["Monitor free disk space on the hydration volume","Enable checksum validation (avoid HeaderFlagNoChecksum in untrusted environments)","Delete partial hydration files on failure so a retry starts clean","Keep page size identical between backup and restore configurations"],"tags":["ltx","decode","restore","checksum"],"backgroundTag":"checksum-mismatch","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"}