{"record":{"id":"89e6db1cd8205c01","repo":"benbjohnson/litestream","slug":"sync-txid-file-w","errorCode":null,"errorMessage":"sync txid file: %w","messagePattern":"sync txid file: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"replica.go","lineNumber":1736,"sourceCode":"// WriteTXIDFile atomically writes a TXID to a sidecar file at <outputPath>-txid.\n// Uses temp-file + fsync + rename for crash safety.\nfunc WriteTXIDFile(outputPath string, txid ltx.TXID) error {\n\ttxidPath := TXIDPath(outputPath)\n\ttmpPath := txidPath + \".tmp\"\n\n\tf, err := os.Create(tmpPath)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"create txid temp file: %w\", err)\n\t}\n\tdefer f.Close()\n\tdefer os.Remove(tmpPath)\n\n\tif _, err := fmt.Fprintln(f, txid); err != nil {\n\t\treturn fmt.Errorf(\"write txid: %w\", err)\n\t}\n\n\tif err := f.Sync(); err != nil {\n\t\treturn fmt.Errorf(\"sync txid file: %w\", err)\n\t}\n\n\tif err := f.Close(); err != nil {\n\t\treturn fmt.Errorf(\"close txid file: %w\", err)\n\t}\n\n\tif err := os.Rename(tmpPath, txidPath); err != nil {\n\t\treturn fmt.Errorf(\"rename txid file: %w\", err)\n\t}\n\n\tif err := internal.FsyncDir(filepath.Dir(txidPath)); err != nil {\n\t\treturn fmt.Errorf(\"sync txid dir: %w\", err)\n\t}\n\treturn nil\n}\n\n// ReadTXIDFile reads the TXID from a sidecar file at <outputPath>-txid.\n// Returns 0, nil if the file does not exist (first run).","sourceCodeStart":1718,"sourceCodeEnd":1754,"githubUrl":"https://github.com/benbjohnson/litestream/blob/4ed7a308f6271ebfd2b0a6e4b70b03011a37e4a3/replica.go#L1718-L1754","documentation":"WriteTXIDFile persists the replica's last-applied TXID to a sidecar '<db>-txid' file using a temp-file + fsync + rename protocol. This error wraps f.Sync(), meaning the OS failed to flush the temp file's data to stable storage. Litestream fsyncs before the atomic rename so the TXID survives a crash; a sync failure means durability cannot be guaranteed for the written TXID.","triggerScenarios":"Calling WriteTXIDFile (directly or via replica restore/apply flows) when the filesystem rejects fsync: full disk on the volume holding the output path, I/O errors on the underlying device, or filesystems/containers where fsync is not supported on the temp file '<outputPath>-txid.tmp'.","commonSituations":"Disk-full on the host or in a Docker container after a large restore; NFS or network filesystems with unreliable fsync; failing disk reported through writeback errors; running in environments (some overlayfs setups) where fsync on a freshly created file errors.","solutions":["Free disk space on the volume containing the output path and retry the operation","Check dmesg / system logs for underlying device I/O errors and repair or replace the failing disk","Verify the output path is on a local filesystem that supports fsync, not an unreliable network mount","Delete any stale '<outputPath>-txid.tmp' file and rerun; the code removes the temp file on error via defer"],"exampleFix":"// before: silently ignoring the write error\nif err := WriteTXIDFile(db.Path(), txid); err != nil { log.Println(err) }\n// after: fail loudly so the caller can resync\nif err := WriteTXIDFile(db.Path(), txid); err != nil {\n    return fmt.Errorf(\"persist txid for %s: %w\", db.Path(), err)\n}","handlingStrategy":"try-catch","validationCode":"// Go: check writable space before writing\nif st, err := os.Statfs(filepath.Dir(TXIDPath(outputPath))); err == nil && st.Bavail*uint64(st.Bsize) < 1<<20 {\n    return fmt.Errorf(\"insufficient disk space for txid file\")\n}","typeGuard":"func canWriteDir(dir string) bool {\n    f, err := os.CreateTemp(dir, \".probe\")\n    if err != nil { return false }\n    f.Close(); os.Remove(f.Name())\n    return true\n}","tryCatchPattern":"if err := WriteTXIDFile(outputPath, txid); err != nil {\n    if errors.Is(err, syscall.ENOSPC) {\n        // free space / alert, then retry\n    } else {\n        return fmt.Errorf(\"persist txid: %w\", err)\n    }\n}","preventionTips":["Monitor free disk space on the volume holding database and sidecar files","Keep database output paths on local POSIX filesystems, not NFS","Ensure the litestream user owns the output directory","Clean stale '*.tmp' sidecar files after crashes"],"tags":["filesystem","fsync","durability","litestream"],"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"}