linera-io/linera-protocol · error
Failed to open log file for writing
Error message
Failed to open log file for writing
What it means
Panic during tracing initialization: `open_log_file` reads `LINERA_LOG_DIR`, joins `log_name` with a `.log` extension, and opens the result with append+create. `create(true)` only creates the file itself, never missing parent directories, so a nonexistent or unwritable LINERA_LOG_DIR (or a path that resolves to a directory) makes `open` fail and `.expect` aborts the whole process at startup. The function returns None (file logging silently disabled) only when the env var is unset.
Source
Thrown at linera-service/src/tracing/mod.rs:141
}
/// Opens a log file for writing.
///
/// The location of the file is determined by the `LINERA_LOG_DIR` environment variable,
/// and its name by the `log_name` parameter.
///
/// Returns [`None`] if the `LINERA_LOG_DIR` environment variable is not set.
pub(crate) fn open_log_file(log_name: &str) -> Option<File> {
let log_directory = env::var_os("LINERA_LOG_DIR")?;
let mut log_file_path = Path::new(&log_directory).join(log_name);
log_file_path.set_extension("log");
Some(
OpenOptions::new()
.append(true)
.create(true)
.open(log_file_path)
.expect("Failed to open log file for writing"),
)
}
#[cfg(not(target_arch = "wasm32"))]
struct WithTraceContext;
#[cfg(not(target_arch = "wasm32"))]
impl<S, N> FormatEvent<S, N> for WithTraceContext
where
S: Subscriber + for<'span> LookupSpan<'span>,
N: for<'writer> FormatFields<'writer> + 'static,
{
fn format_event(
&self,
ctx: &fmt::FmtContext<'_, S, N>,
mut writer: fmt::format::Writer<'_>,
event: &tracing::Event<'_>,
) -> std::fmt::Result {View on GitHub (pinned to 6c226ddcb3)
Solutions
- Pre-create and own the directory as the service user: `mkdir -p "$LINERA_LOG_DIR" && chown $(id -un) "$LINERA_LOG_DIR"` (or add `RuntimeDirectory=linera` to the systemd unit), then restart.
- Unset LINERA_LOG_DIR if file logging is not needed — the code then skips the file layer entirely instead of panicking.
- Verify as the service user: `touch "$LINERA_LOG_DIR/probe.log"`.
- In custom builds, downgrade the expect to a warning plus None so logging init can never kill the process.
Example fix
// before
Some(
OpenOptions::new()
.append(true)
.create(true)
.open(log_file_path)
.expect("Failed to open log file for writing"),
)
// after
match OpenOptions::new().append(true).create(true).open(&log_file_path) {
Ok(file) => Some(file),
Err(err) => {
eprintln!("warning: cannot open log file {}: {err}; file logging disabled", log_file_path.display());
None
}
} Defensive patterns
Strategy: validation
Validate before calling
if let Some(dir) = std::env::var_os("LINERA_LOG_DIR") {
std::fs::create_dir_all(&dir)
.with_context(|| format!("LINERA_LOG_DIR is not creatable: {}", dir.to_string_lossy()))?;
let probe = std::path::Path::new(&dir).join(".probe");
std::fs::write(&probe, b"")?;
std::fs::remove_file(&probe)?;
} Try / catch
// inside open_log_file, replacing the expect:
match OpenOptions::new().append(true).create(true).open(&log_file_path) {
Ok(file) => Some(file),
Err(err) => {
eprintln!("warning: file logging disabled: cannot open {}: {err}", log_file_path.display());
None
}
} Prevention
- Pre-create the log directory in the systemd unit (RuntimeDirectory=linera) or container entrypoint before exec.
- Guard wrapper scripts with `[ -d "$LINERA_LOG_DIR" ] && [ -w "$LINERA_LOG_DIR" ]` before starting the binary.
- Unset LINERA_LOG_DIR in ephemeral/test environments where file logs are unwanted; that path skips file logging without panicking.
- Run the service as a user that owns the logs directory.
When it happens
Trigger: Starting any linera-service binary with LINERA_LOG_DIR set to a directory that does not exist; the directory being owned by another user (EACCES); LINERA_LOG_DIR naming a regular file so the joined `<dir>/<name>.log` cannot be opened; SELinux/AppArmor denying writes to the location.
Common situations: systemd or Docker configs setting LINERA_LOG_DIR=/var/log/linera without RuntimeDirectory= or a pre-created writable volume; running as non-root against root-owned /var/log; setups where the logs volume is no longer mounted after a migration.
Related errors
- Unable to open server config file
- Unable to write server config file
- Unable to open committee configuration
- Failed to write updated server config
- Invalid RUST_LOG_FORMAT: `{format}`. Valid values are `json
AI-assisted analysis of linera-io/linera-protocol@6c226ddcb3 (2026-08-22).
Data as JSON: /api/errors/278c3d89f5e6fe0d.
Report an issue: GitHub.