{"record":{"id":"f1bd11c25db9ffb8","repo":"benbjohnson/litestream","slug":"create-temp-dir-w","errorCode":null,"errorMessage":"create temp dir: %w","messagePattern":"create temp dir: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"vfs.go","lineNumber":357,"sourceCode":"\nfunc (vfs *VFS) requiresTempFile(flags sqlite3vfs.OpenFlag) bool {\n\tconst tempMask = sqlite3vfs.OpenTempDB |\n\t\tsqlite3vfs.OpenTempJournal |\n\t\tsqlite3vfs.OpenSubJournal |\n\t\tsqlite3vfs.OpenSuperJournal |\n\t\tsqlite3vfs.OpenTransientDB |\n\t\tsqlite3vfs.OpenMainJournal\n\tif flags&tempMask != 0 {\n\t\treturn true\n\t}\n\treturn flags&sqlite3vfs.OpenDeleteOnClose != 0\n}\n\nfunc (vfs *VFS) ensureTempDir() (string, error) {\n\tvfs.tempDirOnce.Do(func() {\n\t\tdir, err := os.MkdirTemp(\"\", \"litestream-vfs-*\")\n\t\tif err != nil {\n\t\t\tvfs.tempDirErr = fmt.Errorf(\"create temp dir: %w\", err)\n\t\t\treturn\n\t\t}\n\t\tvfs.tempDir = dir\n\t})\n\treturn vfs.tempDir, vfs.tempDirErr\n}\n\nfunc (vfs *VFS) canonicalTempName(name string) string {\n\tif name == \"\" {\n\t\treturn \"\"\n\t}\n\tname = filepath.Clean(name)\n\tif name == \".\" || name == string(filepath.Separator) {\n\t\treturn \"\"\n\t}\n\treturn name\n}\n","sourceCodeStart":339,"sourceCodeEnd":375,"githubUrl":"https://github.com/benbjohnson/litestream/blob/4ed7a308f6271ebfd2b0a6e4b70b03011a37e4a3/vfs.go#L339-L375","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nos.Setenv(\"TMPDIR\", \"/nonexistent\")\n\n// after\nos.MkdirAll(\"/var/lib/app/tmp\", 0o755)\nos.Setenv(\"TMPDIR\", \"/var/lib/app/tmp\")","handlingStrategy":"validation","validationCode":"dir := os.TempDir()\nfi, err := os.Stat(dir)\nif err != nil || !fi.IsDir() {\n    return fmt.Errorf(\"TMPDIR %q invalid: %w\", dir, err)\n}\nif err := unix.Access(dir, unix.W_OK); err != nil {\n    return fmt.Errorf(\"TMPDIR %q not writable: %w\", dir, err)\n}","typeGuard":null,"tryCatchPattern":"if _, err := os.Stat(vfs.TempDir()); err != nil {\n    // VFS temp dir creation failed permanently (sync.Once cached); recreate the VFS after fixing env\n}","preventionTips":["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."],"tags":["go","filesystem","temp-directory","mkdir"],"backgroundTag":"mkdir-permission-denied","analyzedSha":"4ed7a308f6271ebfd2b0a6e4b70b03011a37e4a3","analyzedAt":"2026-09-06T18:29:25.564Z","contentChangedAt":"2026-09-06T18:29:25.564Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}