{"record":{"id":"abfc19302a1b2067","repo":"benbjohnson/litestream","slug":"open-temp-ltx-file-w","errorCode":null,"errorMessage":"open temp ltx file: %w","messagePattern":"open temp ltx file: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"db.go","lineNumber":2125,"sourceCode":"\tif !info.snapshotting && sz == 0 {\n\t\tdb.Logger.Log(ctx, internal.LevelTrace, \"sync: skip\", \"reason\", \"no new wal pages\")\n\t\treturn result, nil\n\t}\n\n\ttmpFilename := filename + \".tmp\"\n\tif err := internal.MkdirAll(filepath.Dir(tmpFilename), db.dirInfo); err != nil {\n\t\tif isDiskFullError(err) {\n\t\t\treturn result, NewLTXError(\"stage-mkdir\", tmpFilename, 0, uint64(txID), uint64(txID), fmt.Errorf(\"%w: %w\", ErrDiskFull, err))\n\t\t}\n\t\treturn result, err\n\t}\n\n\tltxFile, err := db.openLTXFile(tmpFilename, os.O_RDWR|os.O_CREATE|os.O_TRUNC, mode)\n\tif err != nil {\n\t\tif isDiskFullError(err) {\n\t\t\treturn result, NewLTXError(\"stage-open\", tmpFilename, 0, uint64(txID), uint64(txID), fmt.Errorf(\"%w: %w\", ErrDiskFull, err))\n\t\t}\n\t\treturn result, fmt.Errorf(\"open temp ltx file: %w\", err)\n\t}\n\tdefer func() { _ = os.Remove(tmpFilename) }()\n\tdefer func() { _ = ltxFile.Close() }()\n\n\tuid, gid := internal.Fileinfo(db.fileInfo)\n\t_ = os.Chown(tmpFilename, uid, gid)\n\n\tdb.Logger.Log(ctx, internal.LevelTrace, \"encode header\",\n\t\t\"txid\", txID.String(),\n\t\t\"commit\", commit,\n\t\t\"walOffset\", info.offset,\n\t\t\"walSize\", sz,\n\t\t\"salt1\", rd.salt1,\n\t\t\"salt2\", rd.salt2)\n\n\ttimestamp := time.Now()\n\tenc, err := ltx.NewEncoder(ltxFile)\n\tif err != nil {","sourceCodeStart":2107,"sourceCodeEnd":2143,"githubUrl":"https://github.com/benbjohnson/litestream/blob/4ed7a308f6271ebfd2b0a6e4b70b03011a37e4a3/db.go#L2107-L2143","documentation":"Litestream failed to open the temporary LTX file it uses to stage WAL pages before promoting it to a final LTX file during sync. `db.openLTXFile` calls os.OpenFile with O_RDWR|O_CREATE|O_TRUNC; any open failure (other than disk-full, which is reported as ErrDiskFull) is wrapped here. This means replication for that transaction aborted before any LTX data was written.","triggerScenarios":"Calling sync/replication when the LTX staging directory does not exist, the process lacks write permission on it, the temp filename collides with a directory, or the filesystem is read-only.","commonSituations":"Running litestream as a non-root user against a DB whose replica dir was created by root; mounting the litestream data dir read-only; cleaning up the replica path while litestream runs; SELinux/AppArmor denying writes.","solutions":["Check that the directory holding the temp LTX file exists and is writable by the litestream user (ls -ld, touch a test file).","Verify the filesystem is not mounted read-only (mount | grep).","Fix ownership/permissions on the replica/LTX directory (chown -R litestream:litestream <dir>).","Check for a stale entry with the temp filename that is a directory instead of a file.","Inspect disk-full separately — if dmesg/df show ENOSPC this code path would instead surface ErrDiskFull."],"exampleFix":"// before (root-created replica dir, litestream runs as litestream user)\ndrwx------ root root /var/lib/litestream\n// after\nchown -R litestream:litestream /var/lib/litestream && chmod 750 /var/lib/litestream","handlingStrategy":"validation","validationCode":"const dir = filepath.Dir(ltxStagingPath)\nif st, err := os.Stat(dir); err != nil || !st.IsDir() {\n    return fmt.Errorf(\"staging dir missing: %s\", dir)\n}\nprobe := filepath.Join(dir, \".litestream-probe\")\nif err := os.WriteFile(probe, []byte(\"x\"), 0o644); err != nil {\n    return fmt.Errorf(\"staging dir not writable: %w\", err)\n}\nos.Remove(probe)","typeGuard":null,"tryCatchPattern":"var pathErr *os.PathError\nif errors.As(err, &pathErr) {\n    log.Printf(\"staging file open failed at %s: %v (check perms/existence)\", pathErr.Path, pathErr.Err)\n}","preventionTips":["Provision and chown the litestream data directory to the litestream user before startup","Never mount the litestream state directory read-only","Exclude litestream staging dirs from external cleanup/rotation jobs","Verify writable staging dir in your deployment readiness probe"],"tags":["filesystem","ltx","replication"],"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"}