elkowar/eww · error

Error opening log file

Error message

Error opening log file ({}), for writing

What it means

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.

Solutions

  1. Check that the log file path exists and its parent directory is writable (create missing directories)
  2. Verify XDG_CACHE_HOME / EWW_LOG env vars point to valid writable locations
  3. Run `eww logs`-equivalent check or open the path manually to confirm permissions
  4. Run the daemon as a user with write access to the configured log path

Example fix

// before
std::fs::OpenOptions::new().create(true).append(true).open(&log_file_path)
    .unwrap_or_else(|_| panic!("Error opening log file ({})", log_file_path.as_ref().to_string_lossy()));
// after
if let Some(parent) = log_file_path.as_ref().parent() {
    std::fs::create_dir_all(parent)?;
}
let file = std::fs::OpenOptions::new().create(true).append(true).open(&log_file_path)
    .with_context(|| format!("Error opening log file ({})", log_file_path.as_ref().to_string_lossy()))?;
Defensive patterns

Strategy: fallback

Validate before calling

const path = getLogFilePath();
if (!fs.existsSync(path.dirname(path))) fs.mkdirSync(path.dirname(path), { recursive: true });
fs.accessSync(path.dirname(path), fs.constants.W_OK);

Type guard

function isWritableDir(p) { try { fs.accessSync(p, fs.constants.W_OK); return fs.statSync(p).isDirectory(); } catch { return false; } }

Try / catch

try { startDaemon(); } catch (e) { if (String(e).includes('Error opening log file')) { console.error('Log path unwritable:', e); process.exit(1); } throw e; }

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: "open() failed", "failed to open file", "cannot create file" — what a file open error means and how to fix it — this error's family across 42 libraries.

Related errors


AI-assisted analysis of elkowar/eww@48f5aa8b37 (2026-09-08). Data as JSON: /api/errors/a17cfbba3c13163c. Report an issue: GitHub.

Appendix: source

Thrown at crates/eww/src/server.rs:283

    // detach from terminal
    match unsafe { nix::unistd::fork()? } {
        nix::unistd::ForkResult::Child => {
            nix::unistd::setsid()?;
            match unsafe { nix::unistd::fork()? } {
                nix::unistd::ForkResult::Parent { .. } => std::process::exit(0),
                nix::unistd::ForkResult::Child => {}
            }
        }
        nix::unistd::ForkResult::Parent { .. } => {
            return Ok(ForkResult::Parent);
        }
    }

    let file = std::fs::OpenOptions::new()
        .create(true)
        .append(true)
        .open(&log_file_path)
        .unwrap_or_else(|_| panic!("Error opening log file ({}), for writing", log_file_path.as_ref().to_string_lossy()));
    let fd = file.as_raw_fd();

    if nix::unistd::isatty(1)? {
        nix::unistd::dup2(fd, std::io::stdout().as_raw_fd())?;
    }
    if nix::unistd::isatty(2)? {
        nix::unistd::dup2(fd, std::io::stderr().as_raw_fd())?;
    }

    Ok(ForkResult::Child)
}

/// Ensure the log directory never grows larger than 100MB by deleting files older than 7 days,
/// and truncating all other logfiles to 100MB.
fn cleanup_log_dir(log_dir: impl AsRef<Path>) -> Result<()> {
    // Find all files named "eww_*.log" in the log directory
    let log_files = std::fs::read_dir(&log_dir)?
        .filter_map(|entry| {

View on GitHub (pinned to 48f5aa8b37)