louis-e/arnis · critical

Failed to get main window

Error message

Failed to get main window

What it means

During Tauri app setup, run_gui looks up the window labeled "main" via tauri::Manager::get_webview_window and .expect()s it to exist, storing it for progress notifications. The expect panics with this message when no window labeled "main" was created at that point, aborting startup since the progress reporting path cannot work without it.

Source

Thrown at src/gui.rs:174

            gui_set_save_path,
            gui_pick_save_directory,
            gui_start_generation,
            gui_get_version,
            gui_get_update_info,
            gui_get_platform,
            gui_clear_tile_caches,
            gui_get_world_map_data,
            gui_show_in_folder,
            gui_get_3d_model_attributions,
            gui_get_terrain_preview,
            gui_get_preview_landcover,
            gui_get_preview_buildings,
            gui_log
        ])
        .setup(|app| {
            let app_handle = app.handle();
            let main_window = tauri::Manager::get_webview_window(app_handle, "main")
                .expect("Failed to get main window");
            progress::set_main_window(main_window);
            Ok(())
        })
        .run(tauri::generate_context!())
        .expect("Error while starting the application UI (Tauri)");
}

/// Detects the default Minecraft Java Edition saves directory for the current OS.
/// Checks standard install paths including Flatpak on Linux.
/// Falls back to Desktop, then current directory.
fn detect_minecraft_saves_directory() -> PathBuf {
    // Try standard Minecraft saves directories per OS
    let mc_saves: Option<PathBuf> = if cfg!(target_os = "windows") {
        env::var("APPDATA")
            .ok()
            .map(|appdata| PathBuf::from(appdata).join(".minecraft").join("saves"))
    } else if cfg!(target_os = "macos") {
        dirs::home_dir().map(|home| {

View on GitHub (pinned to 34048924d9)

Solutions

  1. Ensure tauri.conf.json declares a window with label "main" ("label": "main", "visible": true) matching the get_webview_window(app_handle, "main") call.
  2. If windows are created programmatically, create the main window inside .setup() before the lookup, or move the lookup after creation.
  3. Replace .expect with graceful error handling (match/ok_or + early return or eprintln) so a missing window reports a clear message instead of panicking.
  4. Verify the label string is exact — labels are case-sensitive and must match config and lookup.
  5. After a Tauri version upgrade, check the migration guide for window API/config changes and re-run the app with the updated config.

Example fix

// before (src/gui.rs, setup)
let main_window = tauri::Manager::get_webview_window(app_handle, "main")
    .expect("Failed to get main window");
// after
let main_window = tauri::Manager::get_webview_window(app_handle, "main")
    .unwrap_or_else(|| {
        eprintln!("window 'main' not found; check tauri.conf.json labels");
        tauri::WebviewWindowBuilder::new(app_handle, "main", tauri::WebviewUrl::App("index.html".into()))
            .build()
            .expect("Failed to create main window")
    });
Defensive patterns

Strategy: validation

Validate before calling

// at startup, before relying on the window
if let Some(w) = tauri::Manager::get_webview_window(app_handle, "main") {
    progress::set_main_window(w);
} else {
    eprintln!("warning: no window labeled 'main'; progress UI disabled");
}

Type guard

fn main_window_exists(handle: &tauri::AppHandle) -> bool {
    tauri::Manager::get_webview_window(handle, "main").is_some()
}

Try / catch

// Rust has no try-catch for panics; avoid expect and handle the Option:
match tauri::Manager::get_webview_window(app_handle, "main") {
    Some(w) => progress::set_main_window(w),
    None => eprintln!("Failed to get main window; check tauri.conf.json"),
}

Prevention

When it happens

Trigger: The tauri.conf.json (or generate_context! config) defines no window with label "main" (renamed, different label, or windows array empty); the window is created dynamically after setup instead of statically; multiple windows where the main one has a different label; a config refactor or migration dropped the windows section.

Common situations: Renaming the window label in tauri.conf.json (e.g. to the app title) while src/gui.rs still looks up "main"; switching from a static config window to programmatically-created windows placed outside setup; copying run_gui into a new app whose config lacks the window; Tauri v1-to-v2 migration changing Manager::get_webview_window usage/labels.

Related errors


AI-assisted analysis of louis-e/arnis@34048924d9 (2026-09-03). Data as JSON: /api/errors/9e3fc4974638063d. Report an issue: GitHub.