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 element

View on GitHub (pinned to 4ed7a308f6)

Solutions

  1. Check free space and writability of the write-buffer path (WriteBufferPath or os.TempDir()); free space or point WriteBufferPath at a larger volume.
  2. Ensure SetWriteEnabled(true) succeeded before writing — the buffer file must be initialized (initWriteBufferWithLock).
  3. Restart/reopen the VFS file if the buffer file handle was closed externally (e.g. tmpwatch deleted it).
  4. Inspect the wrapped error in logs ('failed to write to buffer') for the exact syscall failure.
  5. 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

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


AI-assisted analysis of benbjohnson/litestream@4ed7a308f6 (2026-09-06). Data as JSON: /api/errors/c59c74160f3c0d02. Report an issue: GitHub.