You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I'm trying to use the dialog API in my Tauri app, specifically the FileDialogBuilder to select files but I'm having some issues with the way it's shown on MacOS (see picture).
It always appears in the top right corner of the screen, overlayed by the menu bar. This file selection window cannot be moved. I'm calling the dialog like this:
FileDialogBuilder::new().pick_folder();
I've used the dialog API for simple Yes/No boxes and it works well so unsure what could be the cause.
Reproduction
I'm not doing anything special to reproduce this issue, just using to open the file dialog.
let file_selection = FileDialogBuilder::new().pick_folder();
Expected behavior
The file selection dialog should not appear on top of the screen, overlayed by the menu bar and blocked (cannot resize it or move it at all).
I'm also seeing this same behavior on macOS. The only workaround seems to be setting a parent window when building the file dialog, which is not ideal. It also makes using the builder a lot less ergonomic (since I need to pass around a window).
Root cause, for anyone still hitting this: the dialog has no parent window, and rfd then picks one for itself.
The plugin only applies a parent if one was set (desktop.rs, if let Some(parent) = d.parent), and the JS OpenDialogOptions has no parent field at all — so every dialog opened from JavaScript arrives with parent: None. rfd then guesses:
// rfd-0.16.0/src/backend/macos/modal_future.rslet win = ifletSome(win) = win {Some(win)}else{unsafe{ app.mainWindow()}.or_else(|| app.windows().firstObject())};// if async exec is possible start sheet modalifunsafe{ app.isRunning()} && win.is_some(){
inner.begin_modal(&window.0,&completion);}
and for the file panel begin_modal is beginSheetModalForWindow_completionHandler (file_dialog/panel_ffi.rs). So the panel is presented as a sheet on whatever that guess produced. mainWindow() is nil whenever the app isn't key — including immediately after a menu item is clicked — so it falls through to app.windows().firstObject(), which is arbitrary.
A sheet attached to the wrong window looks exactly like the screenshot above: pinned somewhere unexpected and impossible to move, because sheets can't be moved.
We hit a worse variant of the same thing on macOS 26.6.2: with the intended window full-screen, the sheet landed on a different window, which for a full-screen window means a different Space. The app was modally blocked by a panel that was nowhere on screen, and Escape was the only way out. Intermittent, because it depends on whether mainWindow() happens to be nil and on the ordering of app.windows().
Workaround until #2563 lands — don't open the dialog from JS; wrap it in your own command and name the parent:
(async so Tauri runs it off the main thread, which is what makes blocking_* safe here.) With the parent named, the sheet attaches to the invoking window every time — verified via the accessibility tree, where the panel now shows up as an AXSheet child of the right window.
Message dialogs go through the same ModalFuture fallback, so they need .parent(&window) too.
Activity
dwosk commentedon Jul 30, 2023
I'm also seeing this same behavior on macOS. The only workaround seems to be setting a parent window when building the file dialog, which is not ideal. It also makes using the builder a lot less ergonomic (since I need to pass around a window).
nicsheen commentedon Sep 24, 2026
Root cause, for anyone still hitting this: the dialog has no parent window, and
rfdthen picks one for itself.The plugin only applies a parent if one was set (
desktop.rs,if let Some(parent) = d.parent), and the JSOpenDialogOptionshas noparentfield at all — so every dialog opened from JavaScript arrives withparent: None.rfdthen guesses:and for the file panel
begin_modalisbeginSheetModalForWindow_completionHandler(file_dialog/panel_ffi.rs). So the panel is presented as a sheet on whatever that guess produced.mainWindow()is nil whenever the app isn't key — including immediately after a menu item is clicked — so it falls through toapp.windows().firstObject(), which is arbitrary.A sheet attached to the wrong window looks exactly like the screenshot above: pinned somewhere unexpected and impossible to move, because sheets can't be moved.
We hit a worse variant of the same thing on macOS 26.6.2: with the intended window full-screen, the sheet landed on a different window, which for a full-screen window means a different Space. The app was modally blocked by a panel that was nowhere on screen, and Escape was the only way out. Intermittent, because it depends on whether
mainWindow()happens to be nil and on the ordering ofapp.windows().Workaround until #2563 lands — don't open the dialog from JS; wrap it in your own command and name the parent:
(
asyncso Tauri runs it off the main thread, which is what makesblocking_*safe here.) With the parent named, the sheet attaches to the invoking window every time — verified via the accessibility tree, where the panel now shows up as anAXSheetchild of the right window.Message dialogs go through the same
ModalFuturefallback, so they need.parent(&window)too.