libnyanpasu/clash-nyanpasu · warning · anyhow::Error

failed to get zoom button

Error message

failed to get zoom button

What it means

Third traffic-light lookup in set_traffic_lights_pos: NSWindow.standardWindowButton(.zoomButton) returned nil, so repositioning the zoom (fullscreen/green) button fails. All three buttons are required to derive the title bar container view.

Source

Thrown at backend/tauri/src/window.rs:919

            (value.x, value.y)
        }
    }

    fn set_traffic_lights_pos(
        window: objc2::rc::Retained<objc2_app_kit::NSWindow>,
        pos: Position,
    ) -> anyhow::Result<()> {
        use objc2_app_kit::NSWindowButton;
        use objc2_foundation::NSRect;
        let close = window
            .standardWindowButton(NSWindowButton::CloseButton)
            .ok_or(anyhow::anyhow!("failed to get close button"))?;
        let miniaturize = window
            .standardWindowButton(NSWindowButton::MiniaturizeButton)
            .ok_or(anyhow::anyhow!("failed to get miniaturize button"))?;
        let zoom = window
            .standardWindowButton(NSWindowButton::ZoomButton)
            .ok_or(anyhow::anyhow!("failed to get zoom button"))?;

        let title_bar_container_view = unsafe {
            close
                .superview()
                .and_then(|view| view.superview())
                .ok_or(anyhow::anyhow!("failed to get title bar container view"))?
        };

        let close_rect = close.frame();
        let button_height = close_rect.size.height;

        let title_bar_frame_height = button_height + pos.y;
        let mut title_bar_rect = title_bar_container_view.frame();
        title_bar_rect.size.height = title_bar_frame_height;
        title_bar_rect.origin.y = window.frame().size.height - title_bar_frame_height;
        unsafe {
            title_bar_container_view.setFrame(title_bar_rect);
        }

View on GitHub (pinned to f7dbce2997)

Solutions

  1. Keep the default decorations (or .fullScreenContentView-related masks) so the zoom button is installed
  2. If the zoom button was intentionally removed, adjust the code to tolerate its absence instead of failing
  3. Invoke after window visibility and retry once; AppKit creates buttons lazily
  4. Fall back to repositioning only close/miniaturize when zoom is missing

Example fix

// before
let zoom = window
    .standardWindowButton(NSWindowButton::ZoomButton)
    .ok_or(anyhow::anyhow!("failed to get zoom button"))?;
// after
let Some(zoom) = window.standardWindowButton(NSWindowButton::ZoomButton) else {
    log::warn!("zoom button unavailable; skipping traffic light reposition");
    return Ok(());
};
Defensive patterns

Strategy: fallback

Validate before calling

if window.standardWindowButton(NSWindowButton::ZoomButton).is_none() {
    return Ok(()); // zoom button removed; skip repositioning
}

Type guard

fn has_zoom(window: &NSWindow) -> bool {
    window.standardWindowButton(NSWindowButton::ZoomButton).is_some()
}

Try / catch

match apply_traffic_lights_pos(window, pos) {
    Err(e) => log::warn!("traffic light reposition skipped: {e}"),
    Ok(()) => {}
}

Prevention

When it happens

Trigger: set_traffic_lights_pos called on a window without the .resizable/.fullScreenButton style components that create the zoom button, borderless windows, or windows where the zoom button was explicitly removed/hidden by prior native code.

Common situations: Tauri windows with decorations:false; apps that removed the zoom button to prevent fullscreen; kiosk-style windows with restricted style masks; calling before the window appears on screen.

Related errors


AI-assisted analysis of libnyanpasu/clash-nyanpasu@f7dbce2997 (2026-09-08). Data as JSON: /api/errors/00797f765e61a1b6. Report an issue: GitHub.