gitbutlerapp/gitbutler · critical
failed to create app settings
Error message
failed to create app settings
What it means
AppSettingsWithDiskSync::new_with_customization (but-settings/src/watch.rs:77) loads settings.json from the config dir - creating it with '{}' when absent - then reads, leniently parses, merges over defaults, and finally deserializes into typed AppSettings (persistence.rs:57-95). Its Result is unwrapped with expect("failed to create app settings"), so startup panics when the file cannot be created/read (IO, permissions), is unparseable even for the lenient parser (truncated file from a crash mid-write), or contains a value whose type contradicts the settings schema.
Source
Thrown at crates/gitbutler-tauri/src/main.rs:72
std::fs::create_dir_all(&config_dir).expect("failed to create config dir");
let custom_settings = cfg!(feature = "packaged-but-distribution")
.then(but_settings::customization::packaged_but_binary);
// While it serves a function, this behavior is sub-optimal. The proper solution is to decouple:
// - Checking for updates from
// - Performing an update
// This way people can be informed that there is an update even if self-updating is not possible (i.e. installed via package manager).
let custom_settings = if cfg!(feature = "disable-auto-updates") {
but_settings::customization::merge_two(
but_settings::customization::disable_auto_update_checks(),
custom_settings,
)
.into()
} else {
custom_settings
};
let mut app_settings =
AppSettingsWithDiskSync::new_with_customization(config_dir.clone(), custom_settings)
.expect("failed to create app settings");
if let Ok(updated_csp) = csp_with_extras(
tauri_context.config().app.security.csp.as_ref().cloned(),
&app_settings,
) {
tauri_context.config_mut().app.security.csp = updated_csp;
};
if let Some(project_to_open) =
std::env::var_os("GITBUTLER_PROJECT_DIR").map(std::path::PathBuf::from)
{
bail!(
"GUI says: how do we tell the frontend to open: {}? \
We could figure out the project-ID while that's important, and pass it along somehow",
project_to_open.display()
);
}
let (app_data_dir, app_cache_dir, app_log_dir) = (View on GitHub (pinned to caf1f223d3)
Solutions
- Rename or delete the settings file so it is regenerated with defaults: mv ~/.config/gitbutler/settings.json ~/.config/gitbutler/settings.json.bak
- Read the error context - it names the exact path and whether reading or parsing failed - and fix the JSON/type problem in place
- Verify the file is readable/writable by the current user and not locked by sync tools
- As a contributor: use ? instead of expect so main() prints the full error chain (see exampleFix)
Example fix
// before
let mut app_settings = AppSettingsWithDiskSync::new_with_customization(config_dir.clone(), custom_settings)
.expect("failed to create app settings");
// after (main() already returns Result, as neighboring `?` calls show)
let mut app_settings = AppSettingsWithDiskSync::new_with_customization(config_dir.clone(), custom_settings)?; Defensive patterns
Strategy: fallback
Validate before calling
// Validate the settings file before app startup
fn settings_file_ok(path: &std::path::Path) -> bool {
match std::fs::read_to_string(path) {
Ok(text) => serde_json::from_str::<serde_json::Value>(&text).is_ok(),
Err(err) if err.kind() == std::io::ErrorKind::NotFound => true,
Err(_) => false,
}
} Prevention
- Back up and regenerate settings.json when startup fails after a crash or downgrade (mv settings.json settings.json.bak)
- Keep settings writes atomic (write-temp-then-rename) if you extend the settings code
- Exclude the config directory from sync tools' partial-file windows, or pause sync during app runtime
When it happens
Trigger: App startup with a corrupted ~/.config/gitbutler/settings.json (partial write after power loss or crash), a settings file from another version with incompatible field types, or IO errors creating/reading the file in the config directory.
Common situations: Forced shutdowns while settings were being saved, hand-edited settings files, sync clients (Dropbox/OneDrive) leaving placeholder or partially-synced files, and downgrades after an upgrade changed a field's type.
Related errors
- failed to create app settings
- failed to create logs dir
- failed to create config dir
- initializing rolling file appender failed
- product name not set
AI-assisted analysis of gitbutlerapp/gitbutler@caf1f223d3 (2026-08-20).
Data as JSON: /api/errors/d900e3cc2b583ee2.
Report an issue: GitHub.