{"record":{"id":"434d2b0c64a5dd0a","repo":"cjpais/Handy","slug":"failed-to-initialize-history-manager","errorCode":null,"errorMessage":"Failed to initialize history manager","messagePattern":"Failed to initialize history manager","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"src-tauri/src/lib.rs","lineNumber":206,"sourceCode":"    // The frontend is responsible for calling the `initialize_enigo` command\n    // after onboarding completes. This avoids triggering permission dialogs\n    // on macOS before the user is ready.\n\n    // Initialize the managers. The audio recorder receives the streaming router\n    // explicitly, so always-on microphone startup can wire live-preview frames\n    // even before Tauri state is populated.\n    let model_manager =\n        Arc::new(ModelManager::new(app_handle).expect(\"Failed to initialize model manager\"));\n    let transcription_manager = Arc::new(\n        TranscriptionManager::new(app_handle, model_manager.clone())\n            .expect(\"Failed to initialize transcription manager\"),\n    );\n    let recording_manager = Arc::new(\n        AudioRecordingManager::new(app_handle, transcription_manager.stream_router())\n            .expect(\"Failed to initialize recording manager\"),\n    );\n    let history_manager =\n        Arc::new(HistoryManager::new(app_handle).expect(\"Failed to initialize history manager\"));\n\n    // Initialize the transcribe-cpp native backend (logging + backend module\n    // registration) once, before any whisper model is loaded.\n    managers::transcription::init_transcribe_backend();\n\n    // Apply accelerator preferences before any model loads\n    managers::transcription::apply_accelerator_settings(app_handle);\n\n    // Add managers to Tauri's managed state\n    app_handle.manage(recording_manager.clone());\n    app_handle.manage(model_manager.clone());\n    app_handle.manage(transcription_manager.clone());\n    app_handle.manage(history_manager.clone());\n    app_handle.manage(tray::TrayState::new());\n\n    // Note: Shortcuts are NOT initialized here.\n    // The frontend is responsible for calling the `initialize_shortcuts` command\n    // after permissions are confirmed (on macOS) or after onboarding completes.","sourceCodeStart":188,"sourceCodeEnd":224,"githubUrl":"https://github.com/cjpais/Handy/blob/ba10ce1943ef34e93c09494027fc0b9ced2e8a44/src-tauri/src/lib.rs#L188-L224","documentation":"Startup panic when HistoryManager::new returns Err. The constructor creates <app_data>/recordings, opens history.db via rusqlite, migrates the legacy tauri-plugin-sql schema, then runs rusqlite_migration to latest — each step can Err: unwritable directory, unopenable/locked/corrupt database, or a migration failure when the stored user_version is newer than the binary's migrations.","triggerScenarios":"Startup calling HistoryManager::new: create_dir_all on recordings fails; Connection::open fails (disk I/O error, file locked by another process); migrate_from_tauri_plugin_sql or Migrations::to_latest fails (schema ahead of the binary, or corrupted schema).","commonSituations":"Downgrading the app after running a newer version (schema user_version ahead of the older binary); history.db corrupted after a crash or power loss; antivirus or sync clients (OneDrive/Dropbox) locking history.db; disk full; app data permissions broken.","solutions":["If you downgraded, install the newest version again instead of running an old binary against a newer schema","Back up and delete/rename history.db so a fresh database is created — history is lost but the app launches","Exclude the app data dir from real-time AV scanning and sync agents to stop file locks","Free disk space and repair permissions on the app data dir"],"exampleFix":"// before\nlet history_manager =\n    Arc::new(HistoryManager::new(app_handle).expect(\"Failed to initialize history manager\"));\n\n// after — history is non-critical: degrade instead of aborting startup\nlet history_manager = Arc::new(match HistoryManager::new(app_handle) {\n    Ok(m) => m,\n    Err(e) => {\n        log::error!(\"history disabled this session: {e:#}\");\n        HistoryManager::new_disabled()\n    }\n});","handlingStrategy":"fallback","validationCode":"// Optional pre-flight: open the db read-only to detect lock/corruption early\nmatch rusqlite::Connection::open_with_flags(\n    app_data.join(\"history.db\"),\n    rusqlite::OpenFlags::SQLITE_OPEN_READ_WRITE,\n) {\n    Ok(_) => {}\n    Err(e) => log::warn!(\"history db may be locked/corrupt: {e}\"),\n}","typeGuard":null,"tryCatchPattern":"match HistoryManager::new(app_handle) {\n    Ok(m) => m,\n    Err(e) if e.to_string().contains(\"user_version\") => {\n        // schema newer than binary: refuse with a clear message, offer app update\n    }\n    Err(_) => {\n        // quarantine: rename history.db to history.db.bak and retry once with a fresh db\n    }\n}","preventionTips":["Refuse to launch (with a clear message) when the stored schema version exceeds the binary's max migration, instead of panicking mid-migration","Quarantine (rename) a corrupt history.db automatically and retry once before giving up","Keep the app data dir out of sync-agent and AV real-time scan scopes to avoid locks on history.db"],"tags":["rust","tauri","sqlite","database-migration","startup","history"],"backgroundTag":"sqlite-database-open-failed","analyzedSha":"ba10ce1943ef34e93c09494027fc0b9ced2e8a44","analyzedAt":"2026-08-17T10:29:55.597Z","contentChangedAt":"2026-08-17T10:29:55.597Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}