{"record":{"id":"16b53f8d12721638","repo":"benbjohnson/litestream","slug":"copy-l0-file-w","errorCode":null,"errorMessage":"copy L0 file: %w","messagePattern":"copy L0 file: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"db.go","lineNumber":1643,"sourceCode":"\treader, err := db.Replica.Client.OpenLTXFile(ctx, 0, minTXID, maxTXID, 0, 0)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"open remote L0 file: %w\", err)\n\t}\n\tdefer func() { _ = reader.Close() }()\n\n\t// Write to temp file and atomically rename\n\tlocalPath := db.LTXPath(0, minTXID, maxTXID)\n\ttmpPath := localPath + \".tmp\"\n\n\ttmpFile, err := os.Create(tmpPath)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"create temp L0 file: %w\", err)\n\t}\n\tdefer func() { _ = os.Remove(tmpPath) }() // Clean up temp file on error\n\n\tif _, err := io.Copy(tmpFile, reader); err != nil {\n\t\t_ = tmpFile.Close()\n\t\treturn fmt.Errorf(\"copy L0 file: %w\", err)\n\t}\n\n\tif err := tmpFile.Sync(); err != nil {\n\t\t_ = tmpFile.Close()\n\t\treturn fmt.Errorf(\"sync L0 file: %w\", err)\n\t}\n\n\tif err := tmpFile.Close(); err != nil {\n\t\treturn fmt.Errorf(\"close L0 file: %w\", err)\n\t}\n\n\t// Atomically rename temp file to final path\n\tif err := os.Rename(tmpPath, localPath); err != nil {\n\t\treturn fmt.Errorf(\"rename L0 file: %w\", err)\n\t}\n\tdb.invalidatePosCache()\n\n\tdb.Logger.Info(\"fetched latest L0 file from replica\",","sourceCodeStart":1625,"sourceCodeEnd":1661,"githubUrl":"https://github.com/benbjohnson/litestream/blob/4ed7a308f6271ebfd2b0a6e4b70b03011a37e4a3/db.go#L1625-L1661","documentation":"After creating the temp file, Litestream streams the remote L0 LTX file into it with io.Copy(tmpFile, reader). This error wraps a failure of that copy: either reading from the remote object or writing to local disk failed mid-stream.","triggerScenarios":"checkDatabaseBehindReplica's io.Copy from the OpenLTXFile reader fails mid-transfer — the object-store connection drops or times out, the remote file is shorter than expected, or the local disk fills while writing.","commonSituations":"Large L0 files over a slow/unstable network link to S3/GCS; object-store returning truncated bodies; proxy or load balancer cutting long connections; local disk filling during the copy.","solutions":["Check network stability to the replica endpoint (curl/aws s3 cp of the same object to test).","Check local disk space — io.Copy fails with ENOSPC if the disk fills mid-stream.","Retry; the temp file is removed automatically on error, so the next sync can redo the fetch cleanly.","If truncation recurs, verify the object's size/etag matches expectations and check storage provider status."],"exampleFix":"// before: single-shot fetch fails on flaky link\nreader, _ := client.OpenLTXFile(ctx, 0, min, max, 0, 0)\nio.Copy(tmpFile, reader)\n// after: rely on litestream retry rather than manual copy — ensure sync interval allows retries\n# litestream.yml\ncheck-interval: 1m  # behind-check re-runs and refetches on next pass","handlingStrategy":"retry","validationCode":"// Pre-check network path to storage before large fetches\nresp, err := http.Head(objectURL)\nif err != nil || resp.StatusCode != 200 { log.Printf(\"storage unreachable\") }","typeGuard":"null","tryCatchPattern":"if _, err := io.Copy(tmpFile, reader); err != nil {\n    _ = tmpFile.Close()\n    return fmt.Errorf(\"copy L0 file: %w\", err)\n} // temp file auto-removed; rely on next-sync retry with backoff","preventionTips":["Use stable, low-latency links to the object store","Configure generous but finite HTTP timeouts","Size the disk for the largest expected L0 file","Avoid aggressive proxies/LBs that kill long-lived connections"],"tags":["litestream","network","io","ltx","object-storage"],"backgroundTag":"network-request-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"}