{"record":{"id":"5f163171e9ffb1b9","repo":"gitbutlerapp/gitbutler","slug":"failed-to-create-logs-dir","errorCode":null,"errorMessage":"failed to create logs dir","messagePattern":"failed to create logs dir","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"crates/gitbutler-tauri/src/logs.rs","lineNumber":14,"sourceCode":"use std::{fs, net::Ipv4Addr, path::Path, time::Duration};\n\nuse tauri::{AppHandle, Manager};\nuse tracing::{Level, instrument, metadata::LevelFilter, subscriber::set_global_default};\nuse tracing_appender::rolling::{RollingFileAppender, Rotation};\nuse tracing_subscriber::{Layer, filter::filter_fn, fmt::format::FmtSpan, layer::SubscriberExt};\n\npub fn init(\n    app_handle: &AppHandle,\n    logs_dir: &Path,\n    performance_logging: bool,\n    enable_tokio_console_log: bool,\n) {\n    fs::create_dir_all(logs_dir).expect(\"failed to create logs dir\");\n\n    let log_prefix = \"GitButler\";\n    let log_suffix = \"log\";\n    let max_log_files = 14;\n    remove_old_logs(logs_dir).ok();\n    let file_appender = RollingFileAppender::builder()\n        .rotation(Rotation::DAILY)\n        .max_log_files(max_log_files)\n        .filename_prefix(log_prefix)\n        .filename_suffix(log_suffix)\n        .build(logs_dir)\n        .expect(\"initializing rolling file appender failed\");\n    let (file_writer, guard) = tracing_appender::non_blocking(file_appender);\n    // As the file-writer only checks `max_log_files` on file rotation, it basically never happens.\n    // Run it now.\n    prune_old_logs(logs_dir, Some(log_prefix), Some(log_suffix), max_log_files).ok();\n\n    app_handle.manage(guard); // keep the guard alive for the lifetime of the app","sourceCodeStart":1,"sourceCodeEnd":32,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/caf1f223d3cfb94488c9198ad34487c6006c648f/crates/gitbutler-tauri/src/logs.rs#L1-L32","documentation":"logs::init() runs inside the Tauri setup hook and first creates the log directory with fs::create_dir_all(logs_dir).expect(\"failed to create logs dir\"). logs_dir comes from but_path::app_log_dir() (~/Library/Logs/<identifier> on macOS, data-local dir/<identifier>/logs elsewhere); mkdir fails on permission denial, a read-only volume, or when a regular file already occupies the path. Because this is a panic in setup, the whole app startup aborts.","triggerScenarios":"Launching the GitButler desktop app where the resolved log directory cannot be created: restrictive permissions on ~/Library/Logs or %LOCALAPPDATA%, a leftover file named like the log directory, sandbox/antivirus interference, or a read-only/full disk.","commonSituations":"Broken user-profile permissions, corporate lockdown policies, disk-full or read-only home volumes, and stale artifacts occupying the target path after migrations.","solutions":["Check write permission on the log dir's parent and remove any regular file occupying the log dir path (ls -la the parent to spot it)","Verify the volume is writable and has space (df -h)","Set E2E_TEST_APP_DATA_DIR to a writable scratch directory to confirm the app works and the environment is the problem","As a contributor: return a Result from logs::init and surface a dialog instead of panicking (see exampleFix)"],"exampleFix":"// before\nfs::create_dir_all(logs_dir).expect(\"failed to create logs dir\");\n\n// after (init returns Result, setup closure propagates)\nfs::create_dir_all(logs_dir)\n    .with_context(|| format!(\"failed to create logs dir {}\", logs_dir.display()))?;","handlingStrategy":"validation","validationCode":"// Pre-flight the log dir before app startup\nfn can_create_log_dir(dir: &std::path::Path) -> bool {\n    std::fs::create_dir_all(dir).is_ok()\n        && dir.metadata().map(|m| m.is_dir()).unwrap_or(false)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Verify writability of the platform log location during installers/first-run checks","Add antivirus/backup exclusions for the app's log directory on managed fleets","Set E2E_TEST_APP_DATA_DIR to a writable path in automation environments"],"tags":["tauri","logging","filesystem","permissions","startup","panic"],"backgroundTag":"permission-denied","analyzedSha":"caf1f223d3cfb94488c9198ad34487c6006c648f","analyzedAt":"2026-08-20T07:55:40.983Z","schemaVersion":2},"datasetVersion":"2026-08-31T22:30:34.772Z"}