linera-io/linera-protocol · error

Failed to create log file

Error message

Failed to create log file

What it means

LoggingExporter::new (linera-exporter/src/runloops/logging_exporter.rs:23) opens the file at Path::new(id.address()) with append+create and expects success. The destination's address string is used directly as a filesystem path, so the panic is an OS open failure: parent directory missing, permission denied, a path component being a directory, or invalid characters for the platform.

Source

Thrown at linera-exporter/src/runloops/logging_exporter.rs:30

///
/// This exporter does not track any state or process data; it simply logs messages to a specified file.
/// It will export events as they occur, never exporting past ones,
/// which can be useful for debugging and monitoring purposes.
pub(crate) struct LoggingExporter {
    id: DestinationId,
    file: std::fs::File,
}

impl LoggingExporter {
    /// Creates a new `LoggingExporter` that logs to the specified file.
    pub fn new(id: DestinationId) -> Self {
        let log_file = Path::new(id.address());
        // Don't truncate the file to preserve previous logs
        let file = OpenOptions::new()
            .append(true)
            .create(true)
            .open(log_file)
            .expect("Failed to create log file");
        LoggingExporter { id, file }
    }

    pub(crate) async fn run_with_shutdown<S, F: IntoFuture<Output = ()>>(
        self,
        shutdown_signal: F,
        storage: ExporterStorage<S>,
    ) -> anyhow::Result<()>
    where
        S: linera_storage::Storage + Clone + Send + Sync + 'static,
    {
        let id = self.id.clone();
        let shutdown_signal_future = shutdown_signal.into_future();
        let mut pinned_shutdown_signal = Box::pin(shutdown_signal_future);

        select! {
            _ = &mut pinned_shutdown_signal => {
                tracing::info!(?id, "logging exporter shutdown signal received, exiting.");

View on GitHub (pinned to 6c226ddcb3)

Solutions

  1. Use a plain, writable file path (absolute if possible) as the LOGGING destination's address.
  2. Create the parent directory before startup: mkdir -p /var/log/linera-exporter.
  3. Check that the process user has write permission on the directory and that no directory occupies the file path.
  4. Confirm the address contains no characters invalid for filenames on the platform.

Example fix

# before: destination address used as file path
address = "validator/logs"   # parent dir may not exist -> panic on open

# after: ensure the directory exists first
mkdir -p /var/lib/linera-exporter
# config
address = "/var/lib/linera-exporter/validator.log"
Defensive patterns

Strategy: validation

Validate before calling

use std::path::Path;

let log_path = Path::new(destination.address());
if let Some(dir) = log_path.parent() {
    if !dir.as_os_str().is_empty() {
        std::fs::create_dir_all(dir)?; // ensure parent exists
    }
}
// fail fast with a clear message instead of a panic
let file = std::fs::OpenOptions::new().append(true).create(true).open(log_path)
    .map_err(|e| anyhow::anyhow!("cannot open log file {}: {e}", log_path.display()))?;

Type guard

fn is_writable_log_path(p: &std::path::Path) -> bool {
    p.parent().map(|d| d.is_dir() && d.metadata().map(|m| !m.permissions().readonly()).unwrap_or(false)).unwrap_or(false)
}

Prevention

When it happens

Trigger: Configuring a LOGGING destination whose address is used as the log-file path and running the exporter where that path cannot be created - e.g. address 'logs/validator.log' with no logs/ directory, a read-only volume, or an address like 'host:1234' producing an unusable path.

Common situations: Running the exporter in a container where the log directory is not mounted/created; address taken from another destination kind (grpc-style host:port) reused for a logging destination; running as a user without write access to the working directory.

Related errors


AI-assisted analysis of linera-io/linera-protocol@6c226ddcb3 (2026-08-22). Data as JSON: /api/errors/ce0b7b82b89d8522. Report an issue: GitHub.