slint-ui/slint · error

root_component() called on a definition built without…

Error message

root_component() called on a definition built without compiler state

What it means

`ComponentDefinition::root_component()` exposes the compiler's `object_tree::Component`, but only if the definition was produced by actual compilation. When the definition came from a source built without compiler state (e.g. created programmatically or from a pre-compiled artifact where `type_loaders.originals` has no entry for `public_index`), the map lookup fails and the code panics. The method is `#[doc(hidden)]` and explicitly not part of the public API contract for such definitions.

Solutions

  1. Only call `root_component()` on definitions returned from the interpreter's `compile()` APIs
  2. Check the definition provenance before introspection; use the public interpreter API (`component_instance`, `set_property`) instead of compiler internals
  3. If you need compiler-level access to a pre-compiled component, compile the source with the interpreter instead of using the macro path
  4. Remove reliance on `#[doc(hidden)]` APIs — they can panic and change without notice

Example fix

// before
let root = definition.root_component(); // may panic
// after
// only for interpreter-compiled definitions:
let (doc, diag, _) = slint_interpreter::compile(
    std::rc::Rc::new(source.into()), None, Default::default(),
).unwrap();
let root = doc.components.last().unwrap().clone();
Defensive patterns

Strategy: type-guard

Validate before calling

// only call root_component on definitions from slint_interpreter::compile
let from_interpreter = matches!(source, Source::InterpreterCompiled);

Prevention

When it happens

Trigger: Calling the `#[doc(hidden)]` `root_component()` on a `ComponentDefinition` obtained from a code path that did not parse/compile `.slint` source with the interpreter's `TypeLoader` — e.g. a definition built for a compiled-binary (Rust macro / pre-compiled) component where `originals` was never populated.

Common situations: Hit by downstream projects that use the interpreter's internal APIs to introspect components loaded from `slint::include_modules!` style pre-compiled definitions instead of `slint_interpreter::compile` results.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


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

Appendix: source

Thrown at internal/interpreter/api.rs:1557

    /// True if instances of this component expose a `slint::Window`-shaped API
    /// (i.e. calling [`ComponentInstance::window`] is meaningful). False for
    /// non-windowed roots such as `SystemTrayIcon`, where `window()` would panic.
    #[doc(hidden)]
    #[cfg(feature = "internal")]
    pub fn is_window(&self) -> bool {
        self.inner.top_level_type() == i_slint_compiler::llr::TopLevelComponentType::Window
    }

    /// This gives access to the tree of Elements.
    #[cfg(feature = "internal")]
    #[doc(hidden)]
    pub fn root_component(&self) -> Rc<i_slint_compiler::object_tree::Component> {
        self.inner
            .type_loaders
            .originals
            .get(self.inner.public_index)
            .expect("root_component() called on a definition built without compiler state")
            .clone()
    }

    /// Return the `TypeLoader` used when parsing the code in the interpreter.
    ///
    /// WARNING: this is not part of the public API
    #[cfg(feature = "internal-highlight")]
    pub fn type_loader(&self) -> std::rc::Rc<i_slint_compiler::typeloader::TypeLoader> {
        self.inner.type_loaders.type_loader.clone().expect(
            "TypeLoader was not retained for this ComponentDefinition (reconstructed from an instance)",
        )
    }

    /// Return the `TypeLoader` used when parsing the code in the interpreter in
    /// a state before most passes were applied by the compiler.
    ///
    /// Each returned type loader is a deep copy of the entire state connected to it,
    /// so this is a fairly expensive function!

View on GitHub (pinned to 3a7e700487)