benbjohnson/litestream · error
create temp dir: %w
Error message
create temp dir: %w
What it means
ensureTempDir lazily creates the shared temp directory (litestream-vfs-*) once per VFS via sync.Once. This error wraps the failure of os.MkdirTemp, stored as tempDirErr and returned on every subsequent call. It is thrown when the OS refuses or fails to create the directory used for temp files, write buffers, and hydration files.
Source
Thrown at vfs.go:357
func (vfs *VFS) requiresTempFile(flags sqlite3vfs.OpenFlag) bool {
const tempMask = sqlite3vfs.OpenTempDB |
sqlite3vfs.OpenTempJournal |
sqlite3vfs.OpenSubJournal |
sqlite3vfs.OpenSuperJournal |
sqlite3vfs.OpenTransientDB |
sqlite3vfs.OpenMainJournal
if flags&tempMask != 0 {
return true
}
return flags&sqlite3vfs.OpenDeleteOnClose != 0
}
func (vfs *VFS) ensureTempDir() (string, error) {
vfs.tempDirOnce.Do(func() {
dir, err := os.MkdirTemp("", "litestream-vfs-*")
if err != nil {
vfs.tempDirErr = fmt.Errorf("create temp dir: %w", err)
return
}
vfs.tempDir = dir
})
return vfs.tempDir, vfs.tempDirErr
}
func (vfs *VFS) canonicalTempName(name string) string {
if name == "" {
return ""
}
name = filepath.Clean(name)
if name == "." || name == string(filepath.Separator) {
return ""
}
return name
}
View on GitHub (pinned to 4ed7a308f6)
Solutions
- Ensure TMPDIR (or /tmp) exists, is writable by the process user, and has free space.
- Set explicit paths in the VFS config (hydration path, buffer path) so the shared temp dir is not required for those features.
- Check container/sandbox policies (PrivateTmp, seccomp, SELinux) that block mkdir in the temp root.
- Restart the process after fixing the environment — the failure is cached in sync.Once for the VFS lifetime.
Example fix
// before
os.Setenv("TMPDIR", "/nonexistent")
// after
os.MkdirAll("/var/lib/app/tmp", 0o755)
os.Setenv("TMPDIR", "/var/lib/app/tmp") Defensive patterns
Strategy: validation
Validate before calling
dir := os.TempDir()
fi, err := os.Stat(dir)
if err != nil || !fi.IsDir() {
return fmt.Errorf("TMPDIR %q invalid: %w", dir, err)
}
if err := unix.Access(dir, unix.W_OK); err != nil {
return fmt.Errorf("TMPDIR %q not writable: %w", dir, err)
} Try / catch
if _, err := os.Stat(vfs.TempDir()); err != nil {
// VFS temp dir creation failed permanently (sync.Once cached); recreate the VFS after fixing env
} Prevention
- Validate TMPDIR at startup with a create/delete probe.
- Never point TMPDIR at read-only or auto-deleted paths.
- Set explicit buffer/hydration paths in VFS config to reduce temp-dir dependence.
- Remember the failure is cached per VFS; fix env before constructing the VFS.
When it happens
Trigger: Any VFS operation that needs the lazily-created temp dir — opening a main DB with hydration enabled but no hydration path, enabling write buffering without a buffer path, or opening temp/transient files (openTempFile) — when os.MkdirTemp("") fails.
Common situations: TMPDIR unset-to-invalid or pointing to a full read-only filesystem; running as a user without write access to the temp root; chroot/container images lacking /tmp; SELinux/AppArmor denying temp directory creation.
Understand the failure class
Background: mkdir permission denied (EACCES): failed to create directory errors explained — this error's family across 32 libraries.
Related errors
- create temp dir for hydration: %w
- create hydration directory: %w
- create parent directory: %w
- recreate L0 directory: %w
- open wal file: %w
AI-assisted analysis of benbjohnson/litestream@4ed7a308f6 (2026-09-06).
Data as JSON: /api/errors/f1bd11c25db9ffb8.
Report an issue: GitHub.