{"record":{"id":"1da2f544cb551a6c","repo":"benbjohnson/litestream","slug":"extract-timestamp-from-ltx-header-w-1da2f5","errorCode":null,"errorMessage":"extract timestamp from LTX header: %w","messagePattern":"extract timestamp from LTX header: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"file/replica_client.go","lineNumber":171,"sourceCode":"\treturn f, nil\n}\n\n// WriteLTXFile writes an LTX file to the replica.\n// Extracts timestamp from LTX header and sets it as the file's ModTime to preserve original creation time.\nfunc (c *ReplicaClient) WriteLTXFile(ctx context.Context, level int, minTXID, maxTXID ltx.TXID, rd io.Reader) (info *ltx.FileInfo, err error) {\n\tvar fileInfo, dirInfo os.FileInfo\n\tif db := c.db(); db != nil {\n\t\tfileInfo, dirInfo = db.FileInfo(), db.DirInfo()\n\t}\n\n\t// Use TeeReader to peek at LTX header while preserving data for upload\n\tvar buf bytes.Buffer\n\tteeReader := io.TeeReader(rd, &buf)\n\n\t// Extract timestamp from LTX header\n\thdr, _, err := ltx.PeekHeader(teeReader)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"extract timestamp from LTX header: %w\", err)\n\t}\n\ttimestamp := time.UnixMilli(hdr.Timestamp).UTC()\n\n\t// Combine buffered data with rest of reader\n\tfullReader := io.MultiReader(&buf, rd)\n\n\t// Ensure parent directory exists.\n\tfilename := c.LTXFilePath(level, minTXID, maxTXID)\n\tif err := internal.MkdirAll(filepath.Dir(filename), dirInfo); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Write LTX file to temporary file next to destination path.\n\ttmpFilename := filename + \".tmp\"\n\tf, err := internal.CreateFile(tmpFilename, fileInfo)\n\tif err != nil {\n\t\treturn nil, err\n\t}","sourceCodeStart":153,"sourceCodeEnd":189,"githubUrl":"https://github.com/benbjohnson/litestream/blob/4ed7a308f6271ebfd2b0a6e4b70b03011a37e4a3/file/replica_client.go#L153-L189","documentation":"Wraps a failure from ltx.PeekHeader when the file replica client reads an incoming LTX stream to extract its timestamp during WriteLTXFile. The header could not be parsed, meaning the payload is not a valid LTX file (empty, truncated, corrupted, or wrong format), so the write is aborted rather than persisting a file with an unknown timestamp.","triggerScenarios":"WriteLTXFile receiving a reader whose first bytes are not a valid LTX header: zero-byte upload, partially flushed writer, corrupted transfer, or a non-LTX payload written to a file replica.","commonSituations":"Disk-full or interrupted transfer producing truncated LTX data; version mismatch between the writer and the ltx package; caller passing an empty or already-consumed reader.","solutions":["Verify the producer emits complete, valid LTX data (check the DB's local LTX files).","Check litestream/ltx library version compatibility between writer and replica.","Re-run replication from the source; if local LTX state is corrupted, use `litestream reset`.","Ensure nothing truncates the stream between producer and replica (disk space, fd limits)."],"exampleFix":"// before\nrd := getReader() // may be empty\n_, err := client.WriteLTXFile(ctx, level, minTXID, maxTXID, rd)\n// after\ndata, err := io.ReadAll(getReader())\nif len(data) == 0 { return fmt.Errorf(\"empty ltx payload, refusing write\") }\n_, err = client.WriteLTXFile(ctx, level, minTXID, maxTXID, bytes.NewReader(data))","handlingStrategy":"validation","validationCode":"hdr, _, err := ltx.PeekHeader(bytes.NewReader(buf.Bytes()))\nif err != nil { return fmt.Errorf(\"payload is not valid LTX: %w\", err) }","typeGuard":null,"tryCatchPattern":"if _, err := client.WriteLTXFile(ctx, level, minTXID, maxTXID, rd); err != nil {\n    if strings.Contains(err.Error(), \"extract timestamp from LTX header\") { return fmt.Errorf(\"corrupt ltx stream: %w\", err) }\n    return err\n}","preventionTips":["Ensure producers write complete LTX files (check disk space, fd limits).","Keep litestream and ltx library versions in sync.","Never feed an already-consumed or empty reader to WriteLTXFile."],"tags":["ltx","corruption","replication","header"],"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"}