benbjohnson/litestream · error

create buffer directory: %w

Error message

create buffer directory: %w

What it means

initWriteBufferWithLock creates the parent directory of the VFS write-buffer file with os.MkdirAll before opening the buffer. This error wraps that MkdirAll failure, meaning the buffer directory could not be created — usually a permissions problem on an ancestor path, or an ancestor existing as a non-directory file.

Source

Thrown at vfs.go:2193

	return pr
}

// initWriteBuffer initializes the write buffer file for durability.
// Any existing buffer content is discarded since unsync'd changes are lost on restart.
// This function acquires f.mu internally.
func (f *VFSFile) initWriteBuffer() error {
	f.mu.Lock()
	defer f.mu.Unlock()
	return f.initWriteBufferWithLock()
}

// initWriteBufferWithLock initializes the write buffer file for durability.
// Any existing buffer content is discarded since unsync'd changes are lost on restart.
// Caller must hold f.mu.
func (f *VFSFile) initWriteBufferWithLock() error {
	// Ensure parent directory exists
	if err := os.MkdirAll(filepath.Dir(f.bufferPath), 0755); err != nil {
		return fmt.Errorf("create buffer directory: %w", err)
	}

	// Open or create buffer file, truncating any existing content
	file, err := os.OpenFile(f.bufferPath, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644)
	if err != nil {
		return fmt.Errorf("open buffer file: %w", err)
	}
	f.bufferFile = file
	f.bufferNextOff = 0

	return nil
}

// writeToBuffer writes a dirty page to the write buffer for durability.
// If the page already exists in the buffer, it overwrites at the same offset.
// Otherwise, it appends to the end of the file.
// Must be called with f.mu held.
func (f *VFSFile) writeToBuffer(pgno uint32, data []byte) error {

View on GitHub (pinned to 4ed7a308f6)

Solutions

  1. Check ownership/permissions of each path component leading to the buffer dir; create the parent manually with correct ownership if needed.
  2. Fix the bufferPath configuration so it points to a writable directory, not inside a file or read-only mount.
  3. In containers, mount a writable volume for the buffer directory or set a writable working path.
  4. Inspect the wrapped syscall error: EACCES → permissions, ENOTDIR → a path component is a file, EROFS → read-only filesystem.

Example fix

// before
bufferPath: /var/tmp/litestream/buffers/app.db.buffer  // /var/tmp/litestream owned by root
// after
sudo mkdir -p /var/tmp/litestream/buffers && sudo chown app:app /var/tmp/litestream/buffers
Defensive patterns

Strategy: validation

Validate before calling

dir := filepath.Dir(bufferPath)
if fi, err := os.Stat(dir); err != nil {
    if err := os.MkdirAll(dir, 0o755); err != nil { return fmt.Errorf("buffer dir not creatable: %w", err) }
} else if !fi.IsDir() { return fmt.Errorf("%s is not a directory", dir) }

Try / catch

if err := db.Open(ctx); err != nil {
    if strings.Contains(err.Error(), "create buffer directory") {
        return fmt.Errorf("fix bufferPath permissions/config: %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: Opening a VFS file with write buffering enabled when filepath.Dir(f.bufferPath) cannot be created: parent dir not writable, path component is a regular file, read-only filesystem, or sandboxed process lacking write access.

Common situations: Misconfigured buffer path pointing inside a file path or read-only mount; running the service as an unprivileged user with an ownership mismatch; containers with read-only root filesystems; SELinux/AppArmor denials.

Understand the failure class

Background: mkdir permission denied (EACCES): failed to create directory errors explained — this error's family across 32 libraries.

Related errors


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