{"record":{"id":"ce0b7b82b89d8522","repo":"linera-io/linera-protocol","slug":"failed-to-create-log-file","errorCode":null,"errorMessage":"Failed to create log file","messagePattern":"Failed to create log file","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"linera-exporter/src/runloops/logging_exporter.rs","lineNumber":30,"sourceCode":"///\n/// This exporter does not track any state or process data; it simply logs messages to a specified file.\n/// It will export events as they occur, never exporting past ones,\n/// which can be useful for debugging and monitoring purposes.\npub(crate) struct LoggingExporter {\n    id: DestinationId,\n    file: std::fs::File,\n}\n\nimpl LoggingExporter {\n    /// Creates a new `LoggingExporter` that logs to the specified file.\n    pub fn new(id: DestinationId) -> Self {\n        let log_file = Path::new(id.address());\n        // Don't truncate the file to preserve previous logs\n        let file = OpenOptions::new()\n            .append(true)\n            .create(true)\n            .open(log_file)\n            .expect(\"Failed to create log file\");\n        LoggingExporter { id, file }\n    }\n\n    pub(crate) async fn run_with_shutdown<S, F: IntoFuture<Output = ()>>(\n        self,\n        shutdown_signal: F,\n        storage: ExporterStorage<S>,\n    ) -> anyhow::Result<()>\n    where\n        S: linera_storage::Storage + Clone + Send + Sync + 'static,\n    {\n        let id = self.id.clone();\n        let shutdown_signal_future = shutdown_signal.into_future();\n        let mut pinned_shutdown_signal = Box::pin(shutdown_signal_future);\n\n        select! {\n            _ = &mut pinned_shutdown_signal => {\n                tracing::info!(?id, \"logging exporter shutdown signal received, exiting.\");","sourceCodeStart":12,"sourceCodeEnd":48,"githubUrl":"https://github.com/linera-io/linera-protocol/blob/6c226ddcb332ef55118dc8d0aafbd093d5420899/linera-exporter/src/runloops/logging_exporter.rs#L12-L48","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"# before: destination address used as file path\naddress = \"validator/logs\"   # parent dir may not exist -> panic on open\n\n# after: ensure the directory exists first\nmkdir -p /var/lib/linera-exporter\n# config\naddress = \"/var/lib/linera-exporter/validator.log\"","handlingStrategy":"validation","validationCode":"use std::path::Path;\n\nlet log_path = Path::new(destination.address());\nif let Some(dir) = log_path.parent() {\n    if !dir.as_os_str().is_empty() {\n        std::fs::create_dir_all(dir)?; // ensure parent exists\n    }\n}\n// fail fast with a clear message instead of a panic\nlet file = std::fs::OpenOptions::new().append(true).create(true).open(log_path)\n    .map_err(|e| anyhow::anyhow!(\"cannot open log file {}: {e}\", log_path.display()))?;","typeGuard":"fn is_writable_log_path(p: &std::path::Path) -> bool {\n    p.parent().map(|d| d.is_dir() && d.metadata().map(|m| !m.permissions().readonly()).unwrap_or(false)).unwrap_or(false)\n}","tryCatchPattern":null,"preventionTips":["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."],"tags":["linera-exporter","logging","file-permissions","panic","rust"],"backgroundTag":"file-permission-denied","analyzedSha":"6c226ddcb332ef55118dc8d0aafbd093d5420899","analyzedAt":"2026-08-22T22:49:09.787Z","schemaVersion":2},"datasetVersion":"2026-08-23T01:17:44.959Z"}