slint-ui/slint · error

the root item of a SystemTrayIcon-rooted component is a…

Error message

the root item of a SystemTrayIcon-rooted component is a SystemTrayIcon

What it means

`set_tray_icon_visible` downcasts the root item (index 0 of the root sub-component) to `SystemTrayIcon` and panics if the cast fails. The invariant holds only when the component's top-level type is actually `SystemTrayIcon`; calling this setter on a component whose root is a `Window` or other type breaks the assumption. This is an internal method guarded by the component's `top_level_type`, so the panic signals an API-surface/state mismatch.

Solutions

  1. Only call `set_tray_icon_visible` when `component_instance.window_adapter_ref`-style checks or `top_level_type() == TopLevelComponentType::SystemTrayIcon` confirm a tray-icon root
  2. Guard the call site by checking the component's declared root type before invoking
  3. If you support mixed components, route through the public `SystemTrayIcon` element API (`set_visible`) instead of internals
  4. Update the Slint interpreter if a regression removed the internal type check

Example fix

// before
instance.set_tray_icon_visible(true); // panics if root isn't SystemTrayIcon
// after
if instance.top_level_type() == i_slint_compiler::llr::TopLevelComponentType::SystemTrayIcon {
    instance.set_tray_icon_visible(true);
}
Defensive patterns

Strategy: validation

Validate before calling

if instance.top_level_type() == i_slint_compiler::llr::TopLevelComponentType::SystemTrayIcon {
    instance.set_tray_icon_visible(true);
}

Prevention

When it happens

Trigger: Calling `set_tray_icon_visible` on a `ComponentInstance` whose root component does not inherit `SystemTrayIcon` — e.g. after refactoring removed the `top_level_type()` guard or the method is invoked on a windowed component by mistake.

Common situations: Developers using interpreter internals to manipulate tray icons hit this when they attach the wrong `.slint` file (one declaring a `Window` root) or when a wrapper library calls the setter unconditionally.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


AI-assisted analysis of slint-ui/slint@3a7e700487 (2026-09-16). Data as JSON: /api/errors/11bcbc97732fa2ed. Report an issue: GitHub.

Appendix: source

Thrown at internal/interpreter/api.rs:1632

impl ComponentInstance {
    /// Return the [`ComponentDefinition`] that was used to create this instance.
    pub fn definition(&self) -> ComponentDefinition {
        ComponentDefinition { inner: std::rc::Rc::new(self.inner.definition()) }
    }

    fn is_system_tray_rooted(&self) -> bool {
        self.inner.top_level_type() == i_slint_compiler::llr::TopLevelComponentType::SystemTrayIcon
    }

    /// Set `visible` directly on the root SystemTrayIcon native item, mirroring
    /// what the Rust/C++ generators emit for tray-rooted public components:
    /// the change-tracker on the item dispatches the value to the platform handle.
    fn set_tray_icon_visible(&self, visible: bool) {
        // The native SystemTrayIcon is item 0 of the root sub-component.
        let item_rc = ItemRc::new(vtable::VRc::into_dyn(self.inner.vrc().clone()), 0);
        let tray = item_rc
            .downcast::<SystemTrayIcon>()
            .expect("the root item of a SystemTrayIcon-rooted component is a SystemTrayIcon");
        tray.as_pin_ref().visible.set(visible);
    }

    /// Return the value for a public property of this component.
    ///
    /// ## Examples
    ///
    /// ```
    /// # i_slint_backend_testing::init_no_event_loop();
    /// use slint_interpreter::{ComponentDefinition, Compiler, Value, SharedString};
    /// let code = r#"
    ///     export component MyWin inherits Window {
    ///         in-out property <int> my_property: 42;
    ///     }
    /// "#;
    /// let mut compiler = Compiler::default();
    /// let result = spin_on::spin_on(
    ///     compiler.build_from_source(code.into(), Default::default()));

View on GitHub (pinned to 3a7e700487)