gitbutlerapp/gitbutler · critical
failed to create logs dir
Error message
failed to create logs dir
What it means
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.
Source
Thrown at crates/gitbutler-tauri/src/logs.rs:14
use std::{fs, net::Ipv4Addr, path::Path, time::Duration};
use tauri::{AppHandle, Manager};
use tracing::{Level, instrument, metadata::LevelFilter, subscriber::set_global_default};
use tracing_appender::rolling::{RollingFileAppender, Rotation};
use tracing_subscriber::{Layer, filter::filter_fn, fmt::format::FmtSpan, layer::SubscriberExt};
pub fn init(
app_handle: &AppHandle,
logs_dir: &Path,
performance_logging: bool,
enable_tokio_console_log: bool,
) {
fs::create_dir_all(logs_dir).expect("failed to create logs dir");
let log_prefix = "GitButler";
let log_suffix = "log";
let max_log_files = 14;
remove_old_logs(logs_dir).ok();
let file_appender = RollingFileAppender::builder()
.rotation(Rotation::DAILY)
.max_log_files(max_log_files)
.filename_prefix(log_prefix)
.filename_suffix(log_suffix)
.build(logs_dir)
.expect("initializing rolling file appender failed");
let (file_writer, guard) = tracing_appender::non_blocking(file_appender);
// As the file-writer only checks `max_log_files` on file rotation, it basically never happens.
// Run it now.
prune_old_logs(logs_dir, Some(log_prefix), Some(log_suffix), max_log_files).ok();
app_handle.manage(guard); // keep the guard alive for the lifetime of the appView on GitHub (pinned to caf1f223d3)
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)
Example fix
// before
fs::create_dir_all(logs_dir).expect("failed to create logs dir");
// after (init returns Result, setup closure propagates)
fs::create_dir_all(logs_dir)
.with_context(|| format!("failed to create logs dir {}", logs_dir.display()))?; Defensive patterns
Strategy: validation
Validate before calling
// Pre-flight the log dir before app startup
fn can_create_log_dir(dir: &std::path::Path) -> bool {
std::fs::create_dir_all(dir).is_ok()
&& dir.metadata().map(|m| m.is_dir()).unwrap_or(false)
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: Broken user-profile permissions, corporate lockdown policies, disk-full or read-only home volumes, and stale artifacts occupying the target path after migrations.
Understand the failure class
Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.
Related errors
- initializing rolling file appender failed
- failed to create config dir
- product name not set
- failed to create app settings
- failed to create app settings
AI-assisted analysis of gitbutlerapp/gitbutler@caf1f223d3 (2026-08-20).
Data as JSON: /api/errors/5f163171e9ffb1b9.
Report an issue: GitHub.