Zackriya-Solutions/meetily · warning

Failed to emit first-launch-detected event

Error message

Failed to emit first-launch-detected event

What it means

Emitter::emit returns tauri::Result and fails when the event cannot be delivered — typically when no live webview window exists or the event channel is unavailable (window creation failed, app tearing down). Here it runs in a spawned task 500ms after setup, so a slow/failed window load or an immediate quit turns the first-launch notification into an async-task panic.

Source

Thrown at frontend/src-tauri/src/database/setup.rs:24

/// Initialize database on app startup
/// Handles first launch detection and conditional initialization
pub async fn initialize_database_on_startup(app: &AppHandle) -> Result<(), String> {
    // Check if this is the first launch (no database exists yet)
    let is_first_launch = DatabaseManager::is_first_launch(app)
        .await
        .map_err(|e| format!("Failed to check first launch status: {}", e))?;

    if is_first_launch {
        info!("First launch detected - will notify window when ready");

        // Delay event emission to ensure window is ready and React listeners are registered
        let app_handle = app.clone();
        tauri::async_runtime::spawn(async move {
            tokio::time::sleep(tokio::time::Duration::from_millis(500)).await;
            app_handle
                .emit("first-launch-detected", ())
                .expect("Failed to emit first-launch-detected event");
            info!("Emitted first-launch-detected after delay");
        });
    } else {
        // Normal flow - initialize database immediately
        let db_manager = DatabaseManager::new_from_app_handle(app)
            .await
            .map_err(|e| format!("Failed to initialize database manager: {}", e))?;

        app.manage(AppState { db_manager });
        info!("Database initialized successfully");
    }

    Ok(())
}

View on GitHub (pinned to 0281737d87)

Solutions

  1. Replace .expect with `if let Err(e) = ... { log::warn!(...) }` — a missed UI notification must never crash
  2. Invert the flow: let the frontend query first-launch status when React mounts, instead of a timed push
  3. Guard emission by checking that at least one webview window exists (app.webview_windows().is_empty()) before emitting

Example fix

// before
app_handle.emit("first-launch-detected", ())
    .expect("Failed to emit first-launch-detected event");

// after
if let Err(e) = app_handle.emit("first-launch-detected", ()) {
    log::warn!("first-launch event not delivered: {e}");
}
Defensive patterns

Strategy: try-catch

Validate before calling

if !app_handle.webview_windows().is_empty() {
    let _ = app_handle.emit("first-launch-detected", ());
}

Try / catch

if let Err(e) = app_handle.emit("first-launch-detected", ()) {
    log::warn!("first-launch event not delivered: {e}");
}

Prevention

When it happens

Trigger: First-launch flow where the main window is still initializing, failed to create, or was closed before the 500ms delay elapsed; emitting during RunEvent::Exit teardown; headless test runs without a real webview.

Common situations: Slow machines where webview startup exceeds the hard-coded 500ms, GPU/webview-runtime issues on Windows, users quitting the app within the first second.

Related errors


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