{"record":{"id":"ebe00d401d3ea249","repo":"benbjohnson/litestream","slug":"init-write-buffer-w","errorCode":null,"errorMessage":"init write buffer: %w","messagePattern":"init write buffer: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"vfs.go","lineNumber":1934,"sourceCode":"\t\t} else if f.vfs != nil {\n\t\t\t// Use VFS temp directory\n\t\t\tdir, err := f.vfs.ensureTempDir()\n\t\t\tif err != nil {\n\t\t\t\tf.mu.Unlock()\n\t\t\t\treturn fmt.Errorf(\"create temp dir for write buffer: %w\", err)\n\t\t\t}\n\t\t\tf.bufferPath = filepath.Join(dir, \"write-buffer\")\n\t\t} else {\n\t\t\t// Fallback to os.TempDir() for cold enable without VFS reference\n\t\t\tf.bufferPath = filepath.Join(os.TempDir(), \"litestream-write-buffer\")\n\t\t}\n\t}\n\n\t// Initialize buffer file if not present\n\tif f.bufferFile == nil {\n\t\tif err := f.initWriteBufferWithLock(); err != nil {\n\t\t\tf.mu.Unlock()\n\t\t\treturn fmt.Errorf(\"init write buffer: %w\", err)\n\t\t}\n\t}\n\n\t// Initialize write tracking state if this is a cold enable\n\tif f.pendingTXID == 0 {\n\t\tf.expectedTXID = f.pos.TXID\n\t\tf.pendingTXID = f.pos.TXID + 1\n\t}\n\n\t// Start sync ticker if not running and interval > 0\n\t// (syncInterval == 0 means no periodic sync, only manual Sync() calls)\n\tif f.syncTicker == nil && f.syncInterval > 0 {\n\t\tf.syncTicker = time.NewTicker(f.syncInterval)\n\t\tf.syncStop = make(chan struct{})\n\t\tstopCh := f.syncStop\n\t\ttickerCh := f.syncTicker.C\n\t\tf.wg.Add(1)\n\t\tgo func() { defer f.wg.Done(); f.syncLoop(stopCh, tickerCh) }()","sourceCodeStart":1916,"sourceCodeEnd":1952,"githubUrl":"https://github.com/benbjohnson/litestream/blob/4ed7a308f6271ebfd2b0a6e4b70b03011a37e4a3/vfs.go#L1916-L1952","documentation":"On a cold enable, SetWriteEnabledWithTimeout(true) tried to create/open the write-buffer file via initWriteBufferWithLock and failed. The write buffer is the local durable file holding dirty pages between SQLite writes and remote LTX syncs, so writes cannot be enabled without it.","triggerScenarios":"SetWriteEnabled(true) when f.bufferFile == nil and the buffer path is unusable: parent directory doesn't exist, permission denied creating the file, disk full, or path exists as a directory. The bufferPath may come from WriteBufferPath, ensureTempDir, or os.TempDir().","commonSituations":"WriteBufferPath pointing to a missing directory (no MkdirAll beforehand); read-only container filesystem; another process holds conflicting permissions on the buffer file; disk full on the volume hosting the buffer; stale buffer file left by a crashed prior process with wrong ownership.","solutions":["Create the buffer directory and grant write permission: mkdir -p <bufferPath dir> && chown appuser it.","Set WriteBufferPath to a verified-writable volume and ensure the directory exists before enabling.","Check the wrapped error for the exact open/create failure (EACCES, ENOSPC, EISDIR) and fix accordingly.","Free disk space on the buffer volume if the error is ENOSPC.","Remove stale litestream-write-buffer files from a previous crashed run if ownership/locks conflict."],"exampleFix":"// before\nvfs.WriteBufferPath = \"/data/litestream\" // dir does not exist\n// after\nos.MkdirAll(\"/data/litestream\", 0o755)\nvfs.WriteBufferPath = \"/data/litestream/write-buffer.bin\"","handlingStrategy":"validation","validationCode":"// Go: validate buffer path before SetWriteEnabled(true)\nfunc validateBufferPath(p string) error {\n    dir := filepath.Dir(p)\n    if fi, err := os.Stat(dir); err != nil || !fi.IsDir() {\n        return fmt.Errorf(\"buffer dir %s unusable: %w\", dir, err)\n    }\n    f, err := os.OpenFile(p, os.O_CREATE|os.O_RDWR, 0o644)\n    if err != nil { return err }\n    return f.Close()\n}","typeGuard":null,"tryCatchPattern":"if err := file.SetWriteEnabled(true); err != nil {\n    if strings.HasPrefix(err.Error(), \"init write buffer:\") {\n        // inspect wrapped *fs.PathError: EACCES/ENOSPC/EISDIR and fix path\n    }\n}","preventionTips":["Create the buffer directory (MkdirAll) before enabling writes.","Keep the buffer on a volume with free space; alert on ENOSPC.","Remove stale buffer files from crashed previous runs.","Exclude the buffer file from external cleanup jobs."],"tags":["go","file-open-failed","write-buffer","permissions","sqlite-vfs"],"backgroundTag":"file-open-failed","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"}