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

  1. Rename or delete the settings file so it is regenerated with defaults: mv ~/.config/gitbutler/settings.json ~/.config/gitbutler/settings.json.bak
  2. Read the error context - it names the exact path and whether reading or parsing failed - and fix the JSON/type problem in place
  3. Verify the file is readable/writable by the current user and not locked by sync tools
  4. 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

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


AI-assisted analysis of gitbutlerapp/gitbutler@caf1f223d3 (2026-08-20). Data as JSON: /api/errors/d900e3cc2b583ee2. Report an issue: GitHub.