benbjohnson/litestream · error

create temp dir for hydration: %w

Error message

create temp dir for hydration: %w

What it means

During xOpen of the Litestream VFS, when hydration is enabled and no explicit hydration path was configured, the VFS must create a temporary OS directory (via os.MkdirTemp) to hold the hydration database file. This error wraps the failure of that directory creation. It is thrown by openMainDB because the VFS cannot prepare local scratch space needed before the main database file can be opened.

Source

Thrown at vfs.go:255

			}
			f.bufferPath = filepath.Join(dir, "write-buffer-"+strconv.FormatUint(writeSeq, 10))
		}

		// Initialize compaction if enabled
		if vfs.CompactionEnabled {
			f.compactor = NewCompactor(client, f.logger)
		}
	}

	// Initialize hydration support if enabled
	if hydrationEnabled {
		if hydrationPath != "" {
			f.hydrationPath = hydrationPath
			f.hydrationPersistent = true
		} else {
			dir, err := vfs.ensureTempDir()
			if err != nil {
				return nil, 0, fmt.Errorf("create temp dir for hydration: %w", err)
			}
			f.hydrationPath = filepath.Join(dir, "hydration.db")
		}
	}

	if err := f.Open(); err != nil {
		if perConnClient {
			if closer, ok := client.(io.Closer); ok {
				closer.Close()
			}
		}
		return nil, 0, err
	}

	if writeEnabled {
		vfs.writeMu.Lock()
		if f.expectedTXID > vfs.lastSyncedTXID {
			vfs.lastSyncedTXID = f.expectedTXID

View on GitHub (pinned to 4ed7a308f6)

Solutions

  1. Check that TMPDIR points to an existing, writable directory and that the volume has free space (df -h $TMPDIR).
  2. Configure an explicit hydration path via the VFS config/URI parameter so the fallback temp dir is never used.
  3. Verify the process user can create directories in the temp location (test with: touch $TMPDIR/probe).
  4. If running in a container, mount a writable tmpfs at /tmp or the configured TMPDIR.

Example fix

// before (failing because TMPDIR is unwritable)
os.Setenv("TMPDIR", "/readonly")
sql.Open("sqlite3", "file:app.db?vfs=litestream")

// after
dir, _ := os.MkdirTemp("", "litestream-check") // or ensure /tmp is writable
os.Setenv("TMPDIR", dir)
sql.Open("sqlite3", "file:app.db?vfs=litestream")
Defensive patterns

Strategy: validation

Validate before calling

dir := os.TempDir()
if fi, err := os.Stat(dir); err != nil || !fi.IsDir() {
    return fmt.Errorf("temp dir %q unusable: %w", dir, err)
}
probe, err := os.CreateTemp(dir, "litestream-probe-*")
if err != nil { return err }
probe.Close(); os.Remove(probe.Name())

Try / catch

f, _, err := vfs.Open(name, flags)
if err != nil && strings.Contains(err.Error(), "create temp dir for hydration") {
    // fix TMPDIR or set explicit hydrationPath, then retry
}

Prevention

When it happens

Trigger: Opening a database through the litestream VFS (sqlite3vfs Open on the registered VFS name) with hydration enabled, no hydrationPath configured, and os.MkdirTemp("") failing — typically because TMPDIR points to a nonexistent/unwritable location or the filesystem is full.

Common situations: Containers run with TMPDIR set to a read-only or deleted directory; disk-full on the temp volume; restricted sandbox (e.g. hardened CI runners) that denies temp directory creation; misconfigured systemd PrivateTmp or seccomp filters blocking mkdir in /tmp.

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/9735bb499ae2fe09. Report an issue: GitHub.