herdrdev/herdr · warning · io::Error

Windows notification setup timed out

Error message

Windows notification setup timed out

What it means

Showing a Windows desktop notification happens on a dedicated thread that signals readiness over a channel. If the thread does not report readiness within 2 seconds, this TimedOut error is returned so callers do not block indefinitely on a stuck WinRT/notification setup.

Source

Thrown at src/platform/windows.rs:2001

    let mut bytes = vec![0_u8; size];
    unsafe {
        copy_nonoverlapping(data.cast::<u8>(), bytes.as_mut_ptr(), size);
        GlobalUnlock(handle);
    }
    Some(bytes)
}

pub fn show_desktop_notification(title: &str, body: Option<&str>) -> std::io::Result<bool> {
    let title = title.to_owned();
    let body = body.unwrap_or(&title).to_owned();
    let (ready_tx, ready_rx) = std::sync::mpsc::sync_channel(1);
    std::thread::Builder::new()
        .name("herdr-windows-notification".into())
        .spawn(move || show_desktop_notification_on_thread(&title, &body, ready_tx))?;
    ready_rx
        .recv_timeout(Duration::from_secs(2))
        .map_err(|err| match err {
            std::sync::mpsc::RecvTimeoutError::Timeout => std::io::Error::new(
                std::io::ErrorKind::TimedOut,
                "Windows notification setup timed out",
            ),
            std::sync::mpsc::RecvTimeoutError::Disconnected => std::io::Error::other(
                "Windows notification thread exited before reporting readiness",
            ),
        })?
}

fn show_desktop_notification_on_thread(
    title: &str,
    body: &str,
    ready_tx: std::sync::mpsc::SyncSender<std::io::Result<bool>>,
) {
    let class_name = wide_null("STATIC");
    let window_name = wide_null("Herdr notifications");
    let hwnd = unsafe {
        CreateWindowExW(

View on GitHub (pinned to f457cff4f2)

Solutions

  1. Retry the notification; transient setup stalls under load usually succeed on a second attempt
  2. Check that Windows notifications are enabled for the app and WpnUserService/WpnService is running
  3. If running over SSH or as a service, ensure an interactive desktop session exists — WinRT toast needs one
  4. Report/inspect Herdr logs for the companion 'thread exited before reporting readiness' error to distinguish a crash from a stall
Defensive patterns

Strategy: retry

Try / catch

match show_desktop_notification(title, body) {
    Ok(()) => {}
    Err(e) if e.kind() == std::io::ErrorKind::TimedOut => {
        // one bounded retry; notifications are best-effort
        let _ = show_desktop_notification(title, body);
    }
    Err(_) => {} // never fail the user flow on a notification
}

Prevention

When it happens

Trigger: Invoking show_desktop_notification on Windows when the spawned notification thread takes longer than the 2-second recv_timeout to initialize (e.g. COM/WinRT initialization stall, system under load, notification service unresponsive).

Common situations: Heavily loaded machines, notification service (WpnService) issues, first COM apartment initialization in a constrained session (SSH/service context without an interactive desktop), or a hung Windows notification API during startup.

Understand the failure class

Related errors


AI-assisted analysis of herdrdev/herdr@f457cff4f2 (2026-08-28). Data as JSON: /api/errors/ac00fe30d2a6567f. Report an issue: GitHub.