sigoden/dufs · error · anyhow::Error

Failed to init logger

Error message

Failed to init logger, {e}

What it means

`main` initializes the global logger (optionally writing to a log file) via `logger::init`. Any underlying error — e.g. the log file cannot be created or opened — is wrapped with anyhow into 'Failed to init logger, {e}' and aborts startup before the server binds.

Solutions

  1. Ensure the log file's parent directory exists and is writable by the process user.
  2. Remove or correct the `--log-file` argument to log to the default destination.
  3. Check filesystem permissions / read-only mounts (e.g. container volumes).
  4. Create the directory first: `mkdir -p $(dirname $LOGFILE)` before starting.

Example fix

// before
duf --log-file /var/log/duf.log   (permission denied)
// after
mkdir -p /var/log && duf --log-file /var/log/duf.log  or use a writable path like ./duf.log
Defensive patterns

Strategy: try-catch

Validate before calling

// before launch
LOGFILE=./duf.log; mkdir -p "$(dirname "$LOGFILE")" && touch "$LOGFILE" || { echo "log path unwritable"; exit 1; }

Try / catch

match logger::init(path) { Ok(_) => {}, Err(e) => eprintln!("continuing without log file: {}", e) }

Prevention

When it happens

Trigger: `--log-file` points to an unwritable path (missing directory, no permissions, path is a directory), or the logger backend fails to install.

Common situations: Running in a read-only container/filesystem; log directory not created before start; running as a non-root user pointing at /var/log; typo'd log path.

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 sigoden/dufs@fe7fd564f8 (2026-09-09). Data as JSON: /api/errors/0c9d730470af41b7. Report an issue: GitHub.

Appendix: source

Thrown at src/main.rs:49

    Arc,
};
use std::time::Duration;
use tokio::time::timeout;
use tokio::{net::TcpListener, task::JoinHandle};
#[cfg(feature = "tls")]
use tokio_rustls::{rustls::ServerConfig, TlsAcceptor};

#[tokio::main]
async fn main() -> Result<()> {
    let cmd = build_cli();
    let matches = cmd.get_matches();
    if let Some(generator) = matches.get_one::<Shell>("completions") {
        let mut cmd = build_cli();
        print_completions(*generator, &mut cmd);
        return Ok(());
    }
    let mut args = Args::parse(matches)?;
    logger::init(args.log_file.clone()).map_err(|e| anyhow!("Failed to init logger, {e}"))?;
    let (new_addrs, print_addrs) = check_addrs(&args)?;
    args.addrs = new_addrs;
    let running = Arc::new(AtomicBool::new(true));
    let listening = print_listening(&args, &print_addrs)?;
    let handles = serve(args, running.clone())?;
    println!("{listening}");

    tokio::select! {
        ret = join_all(handles) => {
            for r in ret {
                if let Err(e) = r {
                    error!("{e}");
                }
            }
            Ok(())
        },
        _ = shutdown_signal() => {
            running.store(false, Ordering::SeqCst);

View on GitHub (pinned to fe7fd564f8)