{"record":{"id":"2d575d0c32d45238","repo":"EpicGames/lore","slug":"failed-to-open-log-file","errorCode":null,"errorMessage":"Failed to open log file {}","messagePattern":"Failed to open log file (.+?)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"lore-chaos-client/src/tracing.rs","lineNumber":13,"sourceCode":"// SPDX-FileCopyrightText: 2026 Epic Games, Inc.\n// SPDX-License-Identifier: MIT\nuse tracing::level_filters::LevelFilter;\nuse tracing_subscriber::Layer;\nuse tracing_subscriber::fmt::layer;\nuse tracing_subscriber::layer::SubscriberExt;\nuse tracing_subscriber::util::SubscriberInitExt;\n\nuse crate::cli::CliArgs;\n\npub fn setup_tracing(args: &CliArgs) {\n    let log_file_layer = std::fs::File::create(&args.log_file)\n        .unwrap_or_else(|_| panic!(\"Failed to open log file {}\", args.log_file));\n\n    let log_layer = layer()\n        .pretty()\n        .with_writer(log_file_layer)\n        .with_ansi(false)\n        .with_filter(LevelFilter::INFO);\n\n    let stdout_filter = if args.log_to_console {\n        LevelFilter::INFO\n    } else {\n        LevelFilter::WARN\n    };\n    let stdout_layer = tracing_subscriber::fmt::layer().with_filter(stdout_filter);\n\n    tracing_subscriber::registry()\n        .with(log_layer)\n        .with(stdout_layer)\n        .init();","sourceCodeStart":1,"sourceCodeEnd":31,"githubUrl":"https://github.com/EpicGames/lore/blob/074eb0b0d1194c997d7cf28b55519e3e197b3e23/lore-chaos-client/src/tracing.rs#L1-L31","documentation":"setup_tracing initializes the tracing subscriber with a pretty log layer writing to a log file passed via CLI args. If std::fs::File::create cannot create/open the log file, the process panics immediately at startup because logging is considered essential. This is a fail-fast design: running without logs would make the chaos client unobservable.","triggerScenarios":"Calling setup_tracing with CliArgs::log_file pointing to a path that cannot be created: non-existent parent directory, no write permission, path is a directory, read-only filesystem, or disk full.","commonSituations":"User passes --log-file /var/log/lore.log without root; typo'd path so the parent dir doesn't exist; container with read-only filesystem; log path colliding with an existing directory.","solutions":["Create the parent directory of the log file (e.g. mkdir -p) or correct the --log-file path.","Check write permissions on the target directory and file.","Choose a writable location such as a path under the user's home or temp directory.","In code, handle the io::Error explicitly instead of unwrapping (fall back to stderr-only logging)."],"exampleFix":"// before\nlet log_file_layer = std::fs::File::create(&args.log_file)\n    .unwrap_or_else(|_| panic!(\"Failed to open log file {}\", args.log_file));\n// after\nlet log_file_layer = std::fs::File::create(&args.log_file)\n    .map_err(|e| anyhow::anyhow!(\"Failed to open log file {}: {e}\", args.log_file))?;","handlingStrategy":"try-catch","validationCode":"if let Err(e) = std::fs::metadata(&args.log_file) { /* path may not exist; check parent */ }\nif let Some(dir) = std::path::Path::new(&args.log_file).parent() {\n    std::fs::create_dir_all(dir)?;\n}","typeGuard":"fn log_file_writable(path: &str) -> bool {\n    std::path::Path::new(path).parent().map(|d| d.is_dir()).unwrap_or(false)\n        && std::fs::OpenOptions::new().append(true).create(true).open(path).is_ok()\n}","tryCatchPattern":"match std::fs::File::create(&args.log_file) {\n    Ok(f) => init_with_file(f),\n    Err(e) => { eprintln!(\"log file unavailable ({}), falling back to stderr\", e); init_stderr_only(); }\n}","preventionTips":["Create the log directory before startup (create_dir_all).","Validate the --log-file path in CLI parsing.","Never panic on logging setup; degrade to stderr instead.","Test the binary in a read-only-filesystem container."],"tags":["rust","logging","file-io","panic"],"backgroundTag":"file-open-failed","analyzedSha":"074eb0b0d1194c997d7cf28b55519e3e197b3e23","analyzedAt":"2026-09-13T09:00:57.509Z","contentChangedAt":"2026-09-13T09:00:57.509Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}