cjpais/Handy · critical
Failed to initialize history manager
Error message
Failed to initialize history manager
What it means
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.
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
Example fix
// before
let history_manager =
Arc::new(HistoryManager::new(app_handle).expect("Failed to initialize history manager"));
// after — history is non-critical: degrade instead of aborting startup
let history_manager = Arc::new(match HistoryManager::new(app_handle) {
Ok(m) => m,
Err(e) => {
log::error!("history disabled this session: {e:#}");
HistoryManager::new_disabled()
}
}); Defensive patterns
Strategy: fallback
Validate before calling
// Optional pre-flight: open the db read-only to detect lock/corruption early
match rusqlite::Connection::open_with_flags(
app_data.join("history.db"),
rusqlite::OpenFlags::SQLITE_OPEN_READ_WRITE,
) {
Ok(_) => {}
Err(e) => log::warn!("history db may be locked/corrupt: {e}"),
} Try / catch
match HistoryManager::new(app_handle) {
Ok(m) => m,
Err(e) if e.to_string().contains("user_version") => {
// schema newer than binary: refuse with a clear message, offer app update
}
Err(_) => {
// quarantine: rename history.db to history.db.bak and retry once with a fresh db
}
} Prevention
- 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
When it happens
Trigger: 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).
Common situations: 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.
Related errors
- error while building tauri application
- Failed to initialize model manager
- Failed to initialize recording manager
- Failed to initialize transcription manager
- Device index ( ) cannot host a model
AI-assisted analysis of cjpais/Handy@ba10ce1943 (2026-08-17).
Data as JSON: /api/errors/434d2b0c64a5dd0a.
Report an issue: GitHub.
Appendix: source
Thrown at src-tauri/src/lib.rs:206
// The frontend is responsible for calling the `initialize_enigo` command
// after onboarding completes. This avoids triggering permission dialogs
// on macOS before the user is ready.
// Initialize the managers. The audio recorder receives the streaming router
// explicitly, so always-on microphone startup can wire live-preview frames
// even before Tauri state is populated.
let model_manager =
Arc::new(ModelManager::new(app_handle).expect("Failed to initialize model manager"));
let transcription_manager = Arc::new(
TranscriptionManager::new(app_handle, model_manager.clone())
.expect("Failed to initialize transcription manager"),
);
let recording_manager = Arc::new(
AudioRecordingManager::new(app_handle, transcription_manager.stream_router())
.expect("Failed to initialize recording manager"),
);
let history_manager =
Arc::new(HistoryManager::new(app_handle).expect("Failed to initialize history manager"));
// Initialize the transcribe-cpp native backend (logging + backend module
// registration) once, before any whisper model is loaded.
managers::transcription::init_transcribe_backend();
// Apply accelerator preferences before any model loads
managers::transcription::apply_accelerator_settings(app_handle);
// Add managers to Tauri's managed state
app_handle.manage(recording_manager.clone());
app_handle.manage(model_manager.clone());
app_handle.manage(transcription_manager.clone());
app_handle.manage(history_manager.clone());
app_handle.manage(tray::TrayState::new());
// Note: Shortcuts are NOT initialized here.
// The frontend is responsible for calling the `initialize_shortcuts` command
// after permissions are confirmed (on macOS) or after onboarding completes.View on GitHub (pinned to ba10ce1943)