{"record":{"id":"fcfd2d269e893653","repo":"gitbutlerapp/gitbutler","slug":"failed-to-create-app-settings","errorCode":null,"errorMessage":"failed to create app settings","messagePattern":"failed to create app settings","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"crates/but-server/src/lib.rs","lineNumber":381,"sourceCode":"            is_localhost_origin(origin.as_bytes())\n        }))\n        .allow_headers(allowed_headers)\n        .allow_credentials(true);\n\n    let config_dir = but_path::app_config_dir().unwrap();\n    let app_data_dir = but_path::app_data_dir().unwrap();\n\n    let broadcaster = Arc::new(Mutex::new(Broadcaster::new()));\n    let archival = Arc::new(but_feedback::Archival {\n        cache_dir: app_data_dir.join(\"cache\").clone(),\n        logs_dir: app_data_dir.join(\"logs\").clone(),\n    });\n    let extra = Extra {\n        active_projects: Arc::new(Mutex::new(ActiveProjects::new())),\n        archival,\n    };\n    let app_settings = AppSettingsWithDiskSync::new_with_customization(config_dir.clone(), None)\n        .expect(\"failed to create app settings\");\n\n    // If a project path was provided, auto-activate that project.\n    if let Some(ref project_path) = config.project_path {\n        match but_ctx::Context::discover(project_path) {\n            Ok(mut ctx) => {\n                but_api::legacy::projects::prepare_project_for_activation(&mut ctx).ok();\n                let mut active = extra.active_projects.lock().await;\n                if active\n                    .set_active(&ctx, &broadcaster, app_settings.clone())\n                    .is_err()\n                {\n                    tracing::warn!(\"Failed to activate project at {}\", project_path.display());\n                }\n            }\n            Err(err) => {\n                tracing::warn!(\n                    \"Could not discover project at {}: {err}\",\n                    project_path.display()","sourceCodeStart":363,"sourceCodeEnd":399,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/2497b8007aa4a1922dae9a805b32ffe5b5037785/crates/but-server/src/lib.rs#L363-L399","documentation":"Startup panic in but-server: AppSettingsWithDiskSync::new_with_customization could not load or create the app settings under the configured config directory. Because this is an expect on server boot, any underlying failure - a corrupt settings file, an unwritable or missing config dir, a path occupied by a file, or a full disk - aborts the whole process before it serves anything.","triggerScenarios":"Starting the server with a config dir mounted read-only (container volume) or owned by another user; settings JSON corrupted by a partial write or manual edit; config_dir pointing at a regular file; ENOSPC when persisting the initial defaults.","commonSituations":"Docker/Kubernetes deployments with mismatched volume mounts; a previous crash interrupting a settings write; running as a service user without ownership of the config directory.","solutions":["Make sure the config directory exists and is writable by the running user","Move aside or delete the existing settings file so a fresh one can be created","Free disk space if writes fail with ENOSPC","Re-run the binary and read the stderr just above the panic for the underlying io/parse error"],"exampleFix":"// before\nlet app_settings = AppSettingsWithDiskSync::new_with_customization(config_dir.clone(), None)\n    .expect(\"failed to create app settings\");\n\n// after\nlet app_settings = AppSettingsWithDiskSync::new_with_customization(config_dir.clone(), None)\n    .map_err(|e| anyhow::anyhow!(\"app settings in {}: {e}\", config_dir.display()))?;","handlingStrategy":"validation","validationCode":"// Pre-flight before server boot: the config dir must be writable\nlet probe = config_dir.join(\".write-probe\");\nstd::fs::write(&probe, b\"\").with_context(|| format!(\"config dir {} not writable\", config_dir.display()))?;\nstd::fs::remove_file(&probe).ok();","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Add a startup healthcheck that validates the config dir (exists, writable, parses) before expect-based code runs","Keep settings writes atomic (write temp file + rename) so crashes cannot corrupt the file","In containers, mount the config volume with correct ownership and read-write mode"],"tags":["rust","panic","server","settings","config-dir","startup"],"backgroundTag":"config-init-failure","analyzedSha":"2497b8007aa4a1922dae9a805b32ffe5b5037785","analyzedAt":"2026-08-17T00:30:25.648Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}