{"record":{"id":"1fd0fa50fce6e3d9","repo":"benbjohnson/litestream","slug":"sync-l0-file-w","errorCode":null,"errorMessage":"sync L0 file: %w","messagePattern":"sync L0 file: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"db.go","lineNumber":1648,"sourceCode":"\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\",\n\t\t\"min_txid\", minTXID,\n\t\t\"max_txid\", maxTXID)\n\n\treturn nil\n}","sourceCodeStart":1630,"sourceCodeEnd":1666,"githubUrl":"https://github.com/benbjohnson/litestream/blob/4ed7a308f6271ebfd2b0a6e4b70b03011a37e4a3/db.go#L1630-L1666","documentation":"After copying, the temp file is flushed to disk with tmpFile.Sync() before rename. This error wraps a failure of fsync on the temp L0 file, meaning the fetched LTX data could not be durably committed to storage and the file is abandoned.","triggerScenarios":"checkDatabaseBehindReplica calls tmpFile.Sync() after a successful io.Copy and the OS returns an error — typically ENOSPC (no space left to flush dirty pages) or EIO (underlying device failure).","commonSituations":"Disk filling up between the copy and the sync; failing or failing-over storage hardware; container filesystems (some overlay/tmpfs setups) returning errors on fsync.","solutions":["Free disk space (df -h) — ENOSPC at fsync time is common even when create/copy succeeded.","Check dmesg/smart data for device I/O errors on the data volume.","If running in a container, verify the storage driver supports reliable fsync (avoid tmpfs for the LTX dir).","Retry after fixing the disk; the .tmp file is cleaned up automatically on error."],"exampleFix":"// before: data volume at 100%\n$ df -h /var/lib/db  # 100% used\n// after: free space or grow volume before restarting litestream\n$ systemctl stop litestream && rm -f /var/lib/db/*.tmp && systemctl start litestream","handlingStrategy":"try-catch","validationCode":"// Keep headroom: fail early if disk is nearly full\nst, _ := os.Statfs(dataDir)\nif st.Bavail*uint64(st.Bsize) < 128*1024*1024 {\n    log.Printf(\"refusing fetch, low disk\")\n}","typeGuard":"null","tryCatchPattern":"if err := tmpFile.Sync(); err != nil {\n    _ = tmpFile.Close()\n    return fmt.Errorf(\"sync L0 file: %w\", err)\n} // ENOSPC -> free space; EIO -> check dmesg for device errors","preventionTips":["Monitor disk free space and alert early","Watch dmesg/smartd for device I/O errors","Avoid tmpfs/overlay quirks for the LTX directory in containers","Leave free-space headroom larger than your largest L0 file"],"tags":["litestream","filesystem","fsync","disk-full","durability"],"backgroundTag":"file-write-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"}