{"record":{"id":"d5e12797c0fbb2a8","repo":"cjpais/Handy","slug":"failed-to-initialize-store","errorCode":null,"errorMessage":"Failed to initialize store","messagePattern":"Failed to initialize store","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"src-tauri/src/settings.rs","lineNumber":1017,"sourceCode":"        self.post_process_providers\n            .iter_mut()\n            .find(|provider| provider.id == provider_id)\n    }\n}\n\n/// Startup entry point. Same load-or-create/salvage/migrate behavior as\n/// `get_settings`; kept as a named alias for call-site clarity, plus a\n/// one-time debug dump of the loaded settings.\npub fn load_or_create_app_settings(app: &AppHandle) -> AppSettings {\n    let settings = get_settings(app);\n    debug!(\"Loaded settings: {:?}\", settings);\n    settings\n}\n\npub fn get_settings(app: &AppHandle) -> AppSettings {\n    let store = app\n        .store(crate::portable::store_path(SETTINGS_STORE_PATH))\n        .expect(\"Failed to initialize store\");\n\n    // Settings reads also persist one-time migrations. Migration helpers are\n    // idempotent, so this converges after the first read of an older store.\n    let mut settings = if let Some(settings_value) = store.get(\"settings\") {\n        let (mut settings, mut updated) =\n            match serde_json::from_value::<AppSettings>(settings_value.clone()) {\n                Ok(settings) => (settings, false),\n                Err(e) => {\n                    warn!(\"Failed to parse stored settings ({e}); salvaging valid fields\");\n                    (salvage_settings(&settings_value), true)\n                }\n            };\n\n        if apply_settings_migrations(&mut settings, &settings_value) {\n            updated = true;\n        }\n\n        // Merge in any bindings added since this store was written.","sourceCodeStart":999,"sourceCodeEnd":1035,"githubUrl":"https://github.com/cjpais/Handy/blob/fbd4e15fa14a721c66c57006ae110428b9e255b3/src-tauri/src/settings.rs#L999-L1035","documentation":"Panic when tauri-plugin-store's app.store(path) fails while reading settings in get_settings. The store builder errors on I/O — creating or opening the settings store file under the app data dir (permission denied, read-only directory, invalid path, disk full). Because get_settings is called at startup, from the idle watcher every 10 seconds, and from many commands, this expect can fire long after launch whenever the filesystem state changes.","triggerScenarios":"Any get_settings call where the store file cannot be created or opened: unwritable app data dir, file locked by another process, full disk, or a broken path in portable mode.","commonSituations":"App data permissions damaged after OS migration; portable mode pointing at an unwritable path; AV/sync agents locking the JSON store; disk filling up while the app runs; path length/charset issues on Windows.","solutions":["Check writability and permissions of the app data dir and the settings store file","Free disk space and exclude the app data dir from sync/AV real-time scanning to remove locks","If the store file itself is corrupt, delete it to regenerate defaults (settings reset) — note parse errors are salvaged, only I/O errors hit this expect","Include the store path and underlying error in the panic message to identify the failing location"],"exampleFix":"// before\nlet store = app\n    .store(crate::portable::store_path(SETTINGS_STORE_PATH))\n    .expect(\"Failed to initialize store\");\n\n// after — name the path and cause in the panic\nlet path = crate::portable::store_path(SETTINGS_STORE_PATH);\nlet store = app\n    .store(path.clone())\n    .unwrap_or_else(|e| panic!(\"Failed to initialize store at {path:?}: {e}\"));","handlingStrategy":"fallback","validationCode":"// Probe store writability once at startup rather than expecting on every read\nlet store = match app.store(crate::portable::store_path(SETTINGS_STORE_PATH)) {\n    Ok(s) => s,\n    Err(e) => {\n        log::error!(\"settings store unavailable: {e}\");\n        return AppSettings::default();\n    }\n};","typeGuard":null,"tryCatchPattern":"match app.store(path) {\n    Ok(store) => store,\n    Err(e) if e.kind() == std::io::ErrorKind::PermissionDenied => {\n        // surface a repair action (fix permissions / free space) and use defaults for this session\n        AppSettings::default()\n    }\n    Err(e) => {\n        log::error!(\"store init failed: {e}\");\n        AppSettings::default()\n    }\n}","preventionTips":["Open the settings store once at startup and cache the handle instead of re-opening on every read (the idle watcher re-runs get_settings every 10 s)","Probe store writability during onboarding and surface a repair screen","Keep the app data dir outside sync/AV-managed folders"],"tags":["rust","tauri","tauri-plugin-store","settings","filesystem"],"backgroundTag":"tauri-store-init-failed","analyzedSha":"fbd4e15fa14a721c66c57006ae110428b9e255b3","analyzedAt":"2026-08-17T10:29:55.597Z","contentChangedAt":"2026-08-17T10:29:55.597Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}