{"record":{"id":"60fefcae51486801","repo":"benbjohnson/litestream","slug":"create-txid-temp-file-w","errorCode":null,"errorMessage":"create txid temp file: %w","messagePattern":"create txid temp file: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"replica.go","lineNumber":1726,"sourceCode":"\t}\n\treturn next.CreatedAt.Before(curr.CreatedAt)\n}\n\n// TXIDPath returns the path to the TXID sidecar file for the given database path.\n// Uses -txid suffix to match SQLite's naming convention for associated files (-wal, -shm).\nfunc TXIDPath(outputPath string) string {\n\treturn outputPath + \"-txid\"\n}\n\n// WriteTXIDFile atomically writes a TXID to a sidecar file at <outputPath>-txid.\n// Uses temp-file + fsync + rename for crash safety.\nfunc WriteTXIDFile(outputPath string, txid ltx.TXID) error {\n\ttxidPath := TXIDPath(outputPath)\n\ttmpPath := txidPath + \".tmp\"\n\n\tf, err := os.Create(tmpPath)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"create txid temp file: %w\", err)\n\t}\n\tdefer f.Close()\n\tdefer os.Remove(tmpPath)\n\n\tif _, err := fmt.Fprintln(f, txid); err != nil {\n\t\treturn fmt.Errorf(\"write txid: %w\", err)\n\t}\n\n\tif err := f.Sync(); err != nil {\n\t\treturn fmt.Errorf(\"sync txid file: %w\", err)\n\t}\n\n\tif err := f.Close(); err != nil {\n\t\treturn fmt.Errorf(\"close txid file: %w\", err)\n\t}\n\n\tif err := os.Rename(tmpPath, txidPath); err != nil {\n\t\treturn fmt.Errorf(\"rename txid file: %w\", err)","sourceCodeStart":1708,"sourceCodeEnd":1744,"githubUrl":"https://github.com/benbjohnson/litestream/blob/4ed7a308f6271ebfd2b0a6e4b70b03011a37e4a3/replica.go#L1708-L1744","documentation":"WriteTXIDFile wraps os.Create failure when creating the temporary file (<txid-path>.tmp) used to atomically persist the restored database's last TXID next to the output. The wrapped cause carries the OS-level reason (permissions, missing directory, disk full).","triggerScenarios":"Restore completing to an output path whose parent directory does not exist, is read-only, or where creating `<output>.txid.tmp` fails (EACCES, ENOSPC, read-only filesystem, sandboxed container FS).","commonSituations":"Restore target inside a non-writable container path; SELinux/AppArmor restrictions; output directory created only after restore started; full disk during DR recovery.","solutions":["Ensure the restore output directory exists and is writable by the litestream process user.","Check available disk space (df -h) and inode/quota limits.","Restore to a different path, then move the files into place.","In containers, mount the target volume with write permissions."],"exampleFix":"// before\n$ litestream restore -o /readonly/db.sqlite db\n// error: create txid temp file: open /readonly/db.sqlite.txid.tmp: permission denied\n// after\n$ mkdir -p /data && chown litestream /data\n$ litestream restore -o /data/db.sqlite db","handlingStrategy":"validation","validationCode":"// Go: verify the output directory is writable before restore\ndir := filepath.Dir(outputPath)\nif info, err := os.Stat(dir); err != nil || !info.IsDir() {\n    return fmt.Errorf(\"output dir missing: %s\", dir)\n}\nprobe, err := os.CreateTemp(dir, \".litestream-probe-*\")\nif err != nil {\n    return fmt.Errorf(\"output dir not writable: %w\", err)\n}\nprobe.Close(); os.Remove(probe.Name())","typeGuard":null,"tryCatchPattern":"if err := WriteTXIDFile(path, txid); err != nil {\n    var perr *fs.PathError\n    if errors.As(err, &perr) {\n        // perr.Err: EACCES/ENOENT/ENOSPC -> fix dir permissions or free space\n    }\n    return err\n}","preventionTips":["Create and chmod the restore output directory before running restore.","Run restores as a user with write access to the target volume.","In containers, mount the target path read-write.","Keep enough free disk for the DB plus its .txid sidecar."],"tags":["restore","filesystem","file-write","temp-file"],"backgroundTag":"file-write-failed","analyzedSha":"4ed7a308f6271ebfd2b0a6e4b70b03011a37e4a3","analyzedAt":"2026-09-06T18:29:25.564Z","contentChangedAt":"2026-09-06T18:29:25.564Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}