slint-ui/slint · error

context shouldn't have been set before

Error message

context shouldn't have been set before

What it means

`WindowInner::set_context` stores the `SlintContext` in a `OnceCell`-like cell and panics if the context was already set. The context must be initialized exactly once before any other window function uses it. A double initialization means two runtime instances are driving the same window machinery.

Solutions

  1. Initialize the Slint context/platform only once per process (guard with std::sync::Once)
  2. Ensure only one copy/version of the slint crate is linked (check `cargo tree -d`)
  3. If writing backend code, check `self.ctx.get().is_some()` before calling set_context
  4. Do not call set_context manually unless implementing a custom backend/platform

Example fix

// before
set_context(ctx);
set_context(ctx); // panics

// after
static INIT: std::sync::Once = std::sync::Once::new();
INIT.call_once(|| set_context(ctx));
Defensive patterns

Strategy: validation

Validate before calling

static INIT: std::sync::Once = std::sync::Once::new();
INIT.call_once(|| slint::platform::set_platform(...).expect("platform init"));

Type guard

fn context_is_unset(w: &slint::WindowInner) -> bool { w.ctx.get().is_none() }

Prevention

When it happens

Trigger: Calling `set_context` twice on the same window, or creating/initializing a component after the context was already installed (e.g. two `slint::Platform`/runtime initializations in the same process).

Common situations: Embedding Slint twice in one process (two independent Slint init calls); mixing static-library copies of slint; custom backend code calling set_context manually; test harnesses that re-initialize the platform per test.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


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

Appendix: source

Thrown at internal/core/window.rs:2509

        self.ctx
            .get_or_init(|| crate::context::GLOBAL_CONTEXT.with(|ctx| ctx.get().unwrap().clone()))
    }

    /// Like [`Self::context`], but returns `None` instead of panicking when no context is
    /// available yet.
    pub fn try_context(&self) -> Option<&crate::SlintContext> {
        if self.ctx.get().is_none()
            && let Some(ctx) = crate::context::GLOBAL_CONTEXT.with(|ctx| ctx.get().cloned())
        {
            let _ = self.ctx.set(ctx);
        }
        self.ctx.get()
    }

    /// Set the SlintContext.
    /// This needs to be called once before any other functions that would use the context.
    pub fn set_context(&self, ctx: crate::SlintContext) {
        self.ctx.set(ctx).map_err(|_| ()).expect("context shouldn't have been set before")
    }
}

/// Internal alias for `Rc<dyn WindowAdapter>`.
pub type WindowAdapterRc = Rc<dyn WindowAdapter>;

/// Resolve the [`crate::SlintContext`] associated with a component root by
/// asking it for (or creating) its window adapter and reading the context off
/// the resulting window. Returns `None` only when no adapter can be produced.
pub fn context_for_root(root: &ItemTreeRc) -> Option<crate::SlintContext> {
    let comp_ref_pin = vtable::VRc::borrow_pin(root);
    let mut adapter = None;
    comp_ref_pin.as_ref().window_adapter(true, &mut adapter);
    adapter.map(|a| WindowInner::from_pub(a.window()).context().clone())
}

/// Runtime entry point for `BuiltinFunction::AccentColor`. Returns the accent color
/// from the component's [`crate::SlintContext`] reached via its window adapter, or

View on GitHub (pinned to 3a7e700487)