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
- 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
- Guard the call site by checking the component's declared root type before invoking
- If you support mixed components, route through the public `SystemTrayIcon` element API (`set_visible`) instead of internals
- 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
- Check `top_level_type()` before any tray-icon-specific call
- Keep a compile-time guarantee that the .slint root is SystemTrayIcon when using tray APIs
- Don't call internal setters unconditionally in wrapper libraries
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
- Cannot get property
- Cannot invoke callback
- Cannot set callback
- Cannot set property
- Global was just valid
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)