zed-industries/zed · error
dialog owner has closed
Error message
dialog owner has closed
What it means
A sentinel validation error raised at the top of show_dialog: before spawning the dialog, Cancellation::is_requested() found the owner window's `closed` flag already set. It means the owning window was destroyed/closed before this dialog request could start, so the request is short-circuited and the receiver immediately gets this Err instead of launching a native dialog thread. There is no dialog to recover; the caller should treat the result as cancelled.
Solutions
- Treat the Err receiver the same as a cancelled dialog: skip awaiting the result or handle it as a no-op
- Check the owner's closed state (DialogOwner::close/when_idle) before issuing dialog requests when the owner may be shutting down
- Do not retry — a closed owner will never accept a new dialog; re-create the owner window first if a dialog is still needed
Defensive patterns
Strategy: validation
When it happens
Trigger: Thrown at crates/gpui_windows/src/dialog.rs:93 when the library encounters an invalid state.
Common situations: See trigger scenarios.
AI-assisted analysis of zed-industries/zed@916fc2b8cb (2026-09-19).
Data as JSON: /api/errors/2997b893497f6067.
Report an issue: GitHub.
Appendix: source
Thrown at crates/gpui_windows/src/dialog.rs:93
.owner_closed
.as_ref()
.is_some_and(|closed| closed.load(Ordering::Acquire))
}
}
/// Native modal loops may synchronously message their owner, so the foreground
/// thread must keep pumping messages rather than waiting for the dialog thread.
/// Holding the owner's lock through native completion also allows window
/// destruction to wait for the dialog without blocking the foreground thread.
pub(crate) fn show_dialog<T: Send + 'static>(
owner: Option<Rc<DialogOwner>>,
executor: &ForegroundExecutor,
dialog: impl FnOnce(HWND) -> Result<T> + Send + 'static,
) -> oneshot::Receiver<Result<T>> {
let (mut sender, receiver) = oneshot::channel();
let cancellation = Cancellation::new(owner.as_deref());
if cancellation.is_requested() {
sender.send(Err(anyhow!("dialog owner has closed"))).ok();
return receiver;
}
let hwnd = owner.as_ref().map(|owner| SafeHwnd::from(owner.hwnd));
executor
.spawn(async move {
// Let Windows manage enabling and activating the owner. Overlapping
// modal loops could otherwise re-enable it while another dialog is open.
let serialization = if let Some(owner) = owner.as_ref() {
match select(owner.serialization.lock(), sender.cancellation()).await {
Either::Left((guard, _)) => Some(guard),
Either::Right(((), _)) => return,
}
} else {
None
};
if sender.is_canceled() || cancellation.is_requested() {
return;
}View on GitHub (pinned to 916fc2b8cb)