{"record":{"id":"34fd883c81b0a6e7","repo":"benbjohnson/litestream","slug":"decode-page-w","errorCode":null,"errorMessage":"decode page: %w","messagePattern":"decode page: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"replica.go","lineNumber":971,"sourceCode":"\tdec := ltx.NewDecoder(rc)\n\tif err := dec.DecodeHeader(); err != nil {\n\t\treturn fmt.Errorf(\"decode header: %w\", err)\n\t}\n\n\thdr := dec.Header()\n\n\tif err := internal.LockFileExclusive(f); err != nil {\n\t\treturn fmt.Errorf(\"acquire exclusive lock: %w\", err)\n\t}\n\tdefer internal.UnlockFile(f)\n\n\tfor {\n\t\tvar phdr ltx.PageHeader\n\t\tdata := make([]byte, pageSize)\n\t\tif err := dec.DecodePage(&phdr, data); err == io.EOF {\n\t\t\tbreak\n\t\t} else if err != nil {\n\t\t\treturn fmt.Errorf(\"decode page: %w\", err)\n\t\t}\n\n\t\tif phdr.Pgno == 1 && len(data) >= 28 {\n\t\t\tdata[18], data[19] = 0x01, 0x01\n\t\t\t_, _ = rand.Read(data[24:28])\n\t\t}\n\n\t\toff := int64(phdr.Pgno-1) * int64(pageSize)\n\t\tif _, err := f.WriteAt(data, off); err != nil {\n\t\t\treturn fmt.Errorf(\"write page %d: %w\", phdr.Pgno, err)\n\t\t}\n\t}\n\n\tif hdr.Commit > 0 {\n\t\tif err := f.Sync(); err != nil {\n\t\t\treturn fmt.Errorf(\"sync before truncate: %w\", err)\n\t\t}\n\t\tnewSize := int64(hdr.Commit) * int64(pageSize)","sourceCodeStart":953,"sourceCodeEnd":989,"githubUrl":"https://github.com/benbjohnson/litestream/blob/4ed7a308f6271ebfd2b0a6e4b70b03011a37e4a3/replica.go#L953-L989","documentation":"This error is returned by Replica.applyLTXFile while streaming pages out of an LTX transaction file during replication/restore. The underlying ltx.Decoder.DecodePage failed, meaning the page stream is corrupt, truncated, or the header/pageSize does not match what was encoded. Litestream treats it as a fatal LTX integrity failure because a partial page application would corrupt the database.","triggerScenarios":"dec.DecodePage returns a non-EOF error inside the page loop: corrupted/truncated LTX file in storage, a remote replica stream interrupted mid-read, an LTX file written by an incompatible LTX format version, or a pageSize mismatch between the DB and the LTX header.","commonSituations":"Interrupted uploads leaving partial LTX objects in S3/GCS, manual edits or re-compression of LTX files, restoring across Litestream versions with differing LTX formats, network disconnects during replica sync/follow mode, storage lifecycle policies truncating objects.","solutions":["Run `litestream reset <db>` to discard corrupted local LTX state and re-sync from the replica","Delete or quarantine the corrupted LTX object in remote storage so the replica re-uploads a valid one","Verify network stability between the host and the storage backend (retries/proxy timeouts)","Confirm the LTX file was produced by a compatible Litestream/LTX version; re-create the replica with a matching version"],"exampleFix":"// before: silently skipping or retrying a corrupt file\ncurrentTXID = info.MaxTXID\n// after: surface the error and reset state\nif err := r.applyLTXFile(ctx, f, info, pageSize); err != nil {\n    return fmt.Errorf(\"decode page: %w\", err) // then run: litestream reset <db>\n}","handlingStrategy":"try-catch","validationCode":"func ltxLooksIntact(info *ltx.FileInfo, rc io.Reader) error {\n    dec := ltx.NewDecoder(rc)\n    if err := dec.DecodeHeader(); err != nil { return err }\n    buf := make([]byte, dec.Header().PageSize)\n    for {\n        var ph ltx.PageHeader\n        if err := dec.DecodePage(&ph, buf); err == io.EOF { break } else if err != nil { return err }\n    }\n    return dec.Close()\n}","typeGuard":null,"tryCatchPattern":"err := r.applyLTXFile(ctx, f, info, pageSize)\nvar ltxErr *ltx.Error\nif errors.As(err, &ltxErr) || strings.Contains(err.Error(), \"decode page\") {\n    // corrupted stream: reset local state and re-sync\n    exec.Command(\"litestream\", \"reset\", dbPath).Run()\n    return fmt.Errorf(\"ltx stream corrupt, state reset: %w\", err)\n}\nreturn err","preventionTips":["Monitor storage object sizes/etags to catch partial uploads","Never modify LTX files after creation; they are immutable","Keep litestream and LTX format versions consistent across replicas","Alert on replication errors immediately — fail silently and corruption compounds"],"tags":["ltx","corruption","replication","restore"],"backgroundTag":"checksum-mismatch","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"}