Zackriya-Solutions/meetily · error · anyhow::Error

App state not available

Error message

App state not available

What it means

`app.try_state::<AppState>()` returns None when no value of exactly type AppState has been registered on the Tauri Builder via `.manage()`. This is a wiring invariant, not a runtime condition: hit at import time (run_import line 636) and inside get_configured_model, it means the app was built without managing AppState, or the command ran on a test AppHandle that skipped setup.

Source

Thrown at frontend/src-tauri/src/audio/import.rs:846

                    warn!("Model discovery error (continuing): {}", e);
                }

                e.load_model(&target_model)
                    .await
                    .map_err(|e| anyhow!("Failed to load model '{}': {}", target_model, e))?;
            }

            Ok(e)
        }
        None => Err(anyhow!("Parakeet engine not initialized")),
    }
}

/// Get the configured model from database
async fn get_configured_model<R: Runtime>(app: &AppHandle<R>, provider_type: &str) -> Result<String> {
    let app_state = app
        .try_state::<AppState>()
        .ok_or_else(|| anyhow!("App state not available"))?;

    let result: Option<(String, String)> = sqlx::query_as(
        "SELECT provider, model FROM transcript_settings WHERE id = '1'",
    )
    .fetch_optional(app_state.db_manager.pool())
    .await
    .map_err(|e| anyhow!("Failed to query config: {}", e))?;

    match result {
        Some((provider, model)) => {
            if (provider_type == "whisper" && (provider == "localWhisper" || provider == "whisper"))
                || (provider_type == "parakeet" && provider == "parakeet")
            {
                Ok(model)
            } else {
                // Return default model for the requested type
                Ok(if provider_type == "parakeet" {
                    DEFAULT_PARAKEET_MODEL.to_string()

View on GitHub (pinned to 0281737d87)

Solutions

  1. Add `.manage(AppState { ... })` to the tauri::Builder in lib.rs, using the same construction as other working commands
  2. Grep for existing `.manage(` calls — the state may be registered under a wrapper type after a refactor
  3. In tests, use tauri's mock runtime with the same setup/manage calls as production
  4. During development, prefer `app.state::<AppState>()` (panics with a clear message) to fail fast on wiring bugs

Example fix

// before
tauri::Builder::default()
    .invoke_handler(tauri::generate_handler![start_import])
    .run(tauri::generate_context!())

// after — register AppState on the builder
tauri::Builder::default()
    .setup(|app| {
        app.manage(AppState { db_manager: init_db(app)? });
        Ok(())
    })
    .invoke_handler(tauri::generate_handler![start_import])
    .run(tauri::generate_context!())
Defensive patterns

Strategy: validation

Validate before calling

// in app setup, fail fast if state wiring is broken
.setup(|app| {
    app.manage(AppState { db_manager });
    assert!(app.try_state::<AppState>().is_some(), "AppState not managed");
    Ok(())
})

Type guard

fn app_state_managed<R: tauri::Runtime>(app: &tauri::AppHandle<R>) -> bool {
    app.try_state::<AppState>().is_some()
}

Try / catch

Not a catchable runtime condition in practice — if hit, fix the Builder wiring: ensure `.manage(AppState { ... })` runs exactly once in the tauri::Builder chain before any command that calls try_state.

Prevention

When it happens

Trigger: The tauri::Builder chain missing `.manage(state)`; state managed under a different or renamed type after a refactor; commands invoked from a mock/test AppHandle that never ran the setup that registers state.

Common situations: A refactor moves manage() into a conditional branch; unit tests build a bare mock app; plugin/setup ordering changes so commands can run before state is managed.

Related errors


AI-assisted analysis of Zackriya-Solutions/meetily@0281737d87 (2026-08-16). Data as JSON: /api/errors/0cff8ac2b08d3566. Report an issue: GitHub.