{"record":{"id":"a17cfbba3c13163c","repo":"elkowar/eww","slug":"error-opening-log-file-for-writing","errorCode":null,"errorMessage":"Error opening log file ({}), for writing","messagePattern":"Error opening log file \\((.+?)\\), for writing","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/eww/src/server.rs","lineNumber":283,"sourceCode":"    // detach from terminal\n    match unsafe { nix::unistd::fork()? } {\n        nix::unistd::ForkResult::Child => {\n            nix::unistd::setsid()?;\n            match unsafe { nix::unistd::fork()? } {\n                nix::unistd::ForkResult::Parent { .. } => std::process::exit(0),\n                nix::unistd::ForkResult::Child => {}\n            }\n        }\n        nix::unistd::ForkResult::Parent { .. } => {\n            return Ok(ForkResult::Parent);\n        }\n    }\n\n    let file = std::fs::OpenOptions::new()\n        .create(true)\n        .append(true)\n        .open(&log_file_path)\n        .unwrap_or_else(|_| panic!(\"Error opening log file ({}), for writing\", log_file_path.as_ref().to_string_lossy()));\n    let fd = file.as_raw_fd();\n\n    if nix::unistd::isatty(1)? {\n        nix::unistd::dup2(fd, std::io::stdout().as_raw_fd())?;\n    }\n    if nix::unistd::isatty(2)? {\n        nix::unistd::dup2(fd, std::io::stderr().as_raw_fd())?;\n    }\n\n    Ok(ForkResult::Child)\n}\n\n/// Ensure the log directory never grows larger than 100MB by deleting files older than 7 days,\n/// and truncating all other logfiles to 100MB.\nfn cleanup_log_dir(log_dir: impl AsRef<Path>) -> Result<()> {\n    // Find all files named \"eww_*.log\" in the log directory\n    let log_files = std::fs::read_dir(&log_dir)?\n        .filter_map(|entry| {","sourceCodeStart":265,"sourceCodeEnd":301,"githubUrl":"https://github.com/elkowar/eww/blob/48f5aa8b379adf29da0b0bb9ca04164f65d8bdaa/crates/eww/src/server.rs#L265-L301","documentation":"When eww daemonizes (do_detach), it redirects stdout/stderr/stdin to a log file. This panic fires when the log file cannot be opened for writing with create+append options via std::fs::OpenOptions. It indicates the daemon could not set up its logging destination.","triggerScenarios":"Calling `eww daemonize` (which runs do_detach via initialize_server) when the log file path's parent directory does not exist, the path is unwritable due to permissions, or the path is invalid on the filesystem.","commonSituations":"XDG_CACHE_HOME or EWW_LOG file environment overrides pointing to nonexistent directories; read-only cache directories; running eww under a user without write permission to the log location; selinux/apparmor restrictions.","solutions":["Check that the log file path exists and its parent directory is writable (create missing directories)","Verify XDG_CACHE_HOME / EWW_LOG env vars point to valid writable locations","Run `eww logs`-equivalent check or open the path manually to confirm permissions","Run the daemon as a user with write access to the configured log path"],"exampleFix":"// before\nstd::fs::OpenOptions::new().create(true).append(true).open(&log_file_path)\n    .unwrap_or_else(|_| panic!(\"Error opening log file ({})\", log_file_path.as_ref().to_string_lossy()));\n// after\nif let Some(parent) = log_file_path.as_ref().parent() {\n    std::fs::create_dir_all(parent)?;\n}\nlet file = std::fs::OpenOptions::new().create(true).append(true).open(&log_file_path)\n    .with_context(|| format!(\"Error opening log file ({})\", log_file_path.as_ref().to_string_lossy()))?;","handlingStrategy":"fallback","validationCode":"const path = getLogFilePath();\nif (!fs.existsSync(path.dirname(path))) fs.mkdirSync(path.dirname(path), { recursive: true });\nfs.accessSync(path.dirname(path), fs.constants.W_OK);","typeGuard":"function isWritableDir(p) { try { fs.accessSync(p, fs.constants.W_OK); return fs.statSync(p).isDirectory(); } catch { return false; } }","tryCatchPattern":"try { startDaemon(); } catch (e) { if (String(e).includes('Error opening log file')) { console.error('Log path unwritable:', e); process.exit(1); } throw e; }","preventionTips":["Ensure the log file's parent directory exists before daemonizing","Check write permissions on XDG cache dirs","Avoid overriding EWW_LOG/XDG_CACHE_HOME with invalid paths","Run the daemon under a user with access to the log path"],"tags":["filesystem","logging","panic","daemon"],"backgroundTag":"file-open-failed","analyzedSha":"48f5aa8b379adf29da0b0bb9ca04164f65d8bdaa","analyzedAt":"2026-09-08T03:13:26.897Z","contentChangedAt":"2026-09-08T03:13:26.897Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}