benbjohnson/litestream · error
copy L0 file: %w
Error message
copy L0 file: %w
What it means
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.
Source
Thrown at db.go:1643
reader, err := db.Replica.Client.OpenLTXFile(ctx, 0, minTXID, maxTXID, 0, 0)
if err != nil {
return fmt.Errorf("open remote L0 file: %w", err)
}
defer func() { _ = reader.Close() }()
// Write to temp file and atomically rename
localPath := db.LTXPath(0, minTXID, maxTXID)
tmpPath := localPath + ".tmp"
tmpFile, err := os.Create(tmpPath)
if err != nil {
return fmt.Errorf("create temp L0 file: %w", err)
}
defer func() { _ = os.Remove(tmpPath) }() // Clean up temp file on error
if _, err := io.Copy(tmpFile, reader); err != nil {
_ = tmpFile.Close()
return fmt.Errorf("copy L0 file: %w", err)
}
if err := tmpFile.Sync(); err != nil {
_ = tmpFile.Close()
return fmt.Errorf("sync L0 file: %w", err)
}
if err := tmpFile.Close(); err != nil {
return fmt.Errorf("close L0 file: %w", err)
}
// Atomically rename temp file to final path
if err := os.Rename(tmpPath, localPath); err != nil {
return fmt.Errorf("rename L0 file: %w", err)
}
db.invalidatePosCache()
db.Logger.Info("fetched latest L0 file from replica",View on GitHub (pinned to 4ed7a308f6)
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.
Example fix
// before: single-shot fetch fails on flaky link reader, _ := client.OpenLTXFile(ctx, 0, min, max, 0, 0) io.Copy(tmpFile, reader) // after: rely on litestream retry rather than manual copy — ensure sync interval allows retries # litestream.yml check-interval: 1m # behind-check re-runs and refetches on next pass
Defensive patterns
Strategy: retry
Validate before calling
// Pre-check network path to storage before large fetches
resp, err := http.Head(objectURL)
if err != nil || resp.StatusCode != 200 { log.Printf("storage unreachable") } Type guard
null
Try / catch
if _, err := io.Copy(tmpFile, reader); err != nil {
_ = tmpFile.Close()
return fmt.Errorf("copy L0 file: %w", err)
} // temp file auto-removed; rely on next-sync retry with backoff Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- open remote L0 file: %w
- get replica position: %w
- read ltx page index: %w
- read ltx page frame: %w
- failed to read response: %w
AI-assisted analysis of benbjohnson/litestream@4ed7a308f6 (2026-09-06).
Data as JSON: /api/errors/16b53f8d12721638.
Report an issue: GitHub.