benbjohnson/litestream · error

clear write buffer

Error message

clear write buffer: %w

What it means

This error is returned after a successful sync when VFSFile.clearWriteBuffer() fails. Litestream's VFS layer stages dirty page data in a temporary write-buffer file for durability; after an LTX transaction commits, the buffer must be cleared (truncated/reset) so it can accumulate the next transaction's pages. The wrap preserves the underlying OS or I/O error from that cleanup step.

Solutions

  1. Check disk space and filesystem health on the volume holding the buffer file (inspect the underlying error wrapped by this message for ENOSPC/EIO).
  2. Verify nothing else deletes or locks the buffer file while the database is open; exclude it from tmp-cleanup jobs.
  3. Restart the process: initWriteBufferWithLock truncates and rebuilds the buffer on open, clearing stale state.
  4. If the wrapped error is permission-related, fix ownership/mode of the buffer directory (0755) and file (0644).

Example fix

// before: buffer file cleaned up externally
// /etc/tmpfiles.d/cleanup.conf
// D /var/tmp/litestream 0755 root root -
// after: persist buffer dir outside tmp cleaner scope
// bufferPath: /var/lib/litestream/buffers/db.buffer
Defensive patterns

Strategy: try-catch

Validate before calling

// Go: check volume writability before opening the DB
if f, err := os.Stat(filepath.Dir(bufferPath)); err != nil || !f.IsDir() { return fmt.Errorf("buffer dir missing: %w", err) }

Try / catch

if err := db.Sync(ctx); err != nil {
    if strings.Contains(err.Error(), "clear write buffer") {
        logger.Error("buffer cleanup failed; restarting DB handle to rebuild buffer", "err", err)
        // reopen DB to re-init write buffer
    }
    return err
}

Prevention

When it happens

Trigger: VFSFile sync succeeds remotely but the subsequent clearWriteBuffer() call fails to truncate or reset the buffer file (disk I/O error, file deleted or locked underneath the VFS, disk full, stale file descriptor after restart).

Common situations: Disk-full conditions on the node hosting the buffer file; the buffer file removed by tmp cleaners or another process; running inside containers with read-only or small tmp volumes; crash-recovery leaving the buffer file in a bad state.

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/154b2810725d1583. Report an issue: GitHub.

Appendix: source

Thrown at vfs.go:2056

		f.cache.Add(pgno, cachedData)
	}

	// Apply synced pages to hydrated file if hydration is complete
	// Must be done before clearing f.dirty since we need the page offsets
	if f.hydrator != nil && f.hydrator.Complete() {
		if err := f.applySyncedPagesToHydratedFile(); err != nil {
			f.logger.Error("failed to apply synced pages to hydrated file", "error", err)
			// Don't fail the sync - hydration will catch up on next poll
		}
	}

	// Clear dirty pages
	f.dirty = make(map[uint32]int64)

	// Clear write buffer after successful sync
	if err := f.clearWriteBuffer(); err != nil {
		f.logger.Error("failed to clear write buffer", "error", err)
		return fmt.Errorf("clear write buffer: %w", err)
	}

	return nil
}

// checkForConflict checks if the remote has newer transactions than expected.
// Must be called with f.mu held.
func (f *VFSFile) checkForConflict(ctx context.Context) error {
	// Get latest remote position
	itr, err := f.client.LTXFiles(ctx, 0, f.expectedTXID, false)
	if err != nil {
		return fmt.Errorf("check remote position: %w", err)
	}
	defer itr.Close()

	var remoteTXID ltx.TXID
	for itr.Next() {
		info := itr.Item()

View on GitHub (pinned to 4ed7a308f6)