benbjohnson/litestream · critical
write to buffer: %w
Error message
write to buffer: %w
What it means
VFSFile.WriteAt failed while appending the modified page into the local durable write buffer file (the tmpfs-backed file holding dirty pages before they are synced to the replica as an LTX file). The wrapped error comes from writeToBuffer, typically a disk I/O failure on the buffer file (write, grow, or flush). Since this is a disaster-recovery path, the write is aborted so the page is not reported as persisted.
Source
Thrown at vfs.go:1686
// Page is not dirty - read from cache/remote
if err := f.readPageForWrite(pgno, page); err != nil {
// If page doesn't exist, use zero-filled page
f.logger.Debug("page not found, using empty page", "pgno", pgno)
}
}
// Apply write to page
n = copy(page[pageOffset:], b)
// Update commit count if this extends the database
if pgno > f.commit {
f.commit = pgno
}
// Write to buffer for durability (this updates f.dirty with the offset)
if err := f.writeToBuffer(pgno, page); err != nil {
f.logger.Error("failed to write to buffer", "error", err)
return 0, fmt.Errorf("write to buffer: %w", err)
}
f.logger.Debug("wrote to dirty page", "pgno", pgno, "offset", pageOffset, "len", n, "commit", f.commit)
return n, nil
}
// readPageForWrite reads a page into buf for modification.
// Must be called with f.mu held.
func (f *VFSFile) readPageForWrite(pgno uint32, buf []byte) error {
pageSize := uint32(len(buf))
// Check cache first (cache is thread-safe, but we hold the lock anyway)
if data, ok := f.cache.Get(pgno); ok {
copy(buf, data)
return nil
}
// Get page index elementView on GitHub (pinned to 4ed7a308f6)
Solutions
- Check free space and writability of the write-buffer path (WriteBufferPath or os.TempDir()); free space or point WriteBufferPath at a larger volume.
- Ensure SetWriteEnabled(true) succeeded before writing — the buffer file must be initialized (initWriteBufferWithLock).
- Restart/reopen the VFS file if the buffer file handle was closed externally (e.g. tmpwatch deleted it).
- Inspect the wrapped error in logs ('failed to write to buffer') for the exact syscall failure.
- Retry the transaction after fixing disk conditions; dirty state is unchanged on failure.
Example fix
// before
vfs, _ := litestreamvfs.New(..., litestreamvfs.WithWriteEnabled(true)) // temp dir on small tmpfs
// after
cfg.VFS.WriteBufferPath = "/var/lib/litestream/write-buffer" // persistent volume with space
if err := file.SetWriteEnabled(true); err != nil { log.Fatal(err) } Defensive patterns
Strategy: try-catch
Validate before calling
// Go
func canWriteBuffer(path string) error {
fi, err := os.Stat(filepath.Dir(path))
if err != nil { return err }
if !fi.IsDir() { return fmt.Errorf("not a dir") }
f, err := os.CreateTemp(filepath.Dir(path), ".probe")
if err != nil { return err }
f.Close(); os.Remove(f.Name())
return nil
} Try / catch
n, err := file.WriteAt(buf, off)
if err != nil {
var werr *fs.PathError
if errors.As(err, &werr) { log.Errorf("buffer I/O: %v", werr.Err) }
// surface to SQLite as IOERR; check disk space before retry
} Prevention
- Provision the write-buffer volume with headroom for your largest transaction.
- Set WriteBufferPath explicitly to a persistent writable path instead of TMPDIR.
- Monitor disk free space on the buffer volume.
- Exclude the buffer path from tmp-cleaner/tmpwatch jobs.
When it happens
Trigger: Calling SQLite writes (via the sqlite3vfs VFS) when writeEnabled is true and writeToBuffer cannot write the page into the buffer file: disk full, buffer file closed/never initialized, or I/O error on the temp filesystem. Also triggered when the buffer file handle is stale after a sync cleared the buffer.
Common situations: Temp directory (WriteBufferPath or os.TempDir) on a full or read-only disk; container with a small tmpfs that fills with large transactions; buffer file deleted out from under a running process (e.g. tmp cleaner); calling SetWriteEnabled(true) on a VFSFile constructed without a proper buffer path.
Understand the failure class
Background: "failed to write file", "Could not save figure", "Error saving remote file" — file write failed: causes and fixes across languages and libraries — this error's family across 38 libraries.
Related errors
- init write buffer: %w
- read page %d from buffer for cache: %w
- stage-sync
- stage-close
- list generations: %w
AI-assisted analysis of benbjohnson/litestream@4ed7a308f6 (2026-09-06).
Data as JSON: /api/errors/c59c74160f3c0d02.
Report an issue: GitHub.