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
- Use a plain, writable file path (absolute if possible) as the LOGGING destination's address.
- Create the parent directory before startup: mkdir -p /var/log/linera-exporter.
- Check that the process user has write permission on the directory and that no directory occupies the file path.
- 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
- Use absolute file paths for LOGGING destination addresses, one per destination.
- Create and chown log directories in the service unit (ExecStartPre=/usr/bin/mkdir -p ...) or container entrypoint.
- Never reuse host:port-style addresses as logging destination addresses.
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
- Unable to read the configuration file
- Failed to clone storage
- owner should be different from spender
- invalid block export configuration: {message}
- Returned AccountInfo should have code: Some(...) and so code
AI-assisted analysis of linera-io/linera-protocol@6c226ddcb3 (2026-08-22).
Data as JSON: /api/errors/ce0b7b82b89d8522.
Report an issue: GitHub.