slint-ui/slint · error
platform already initialized
Error message
platform already initialized
What it means
`init_no_event_loop` in the testing backend installs the testing platform via `set_platform`, which can only succeed once per process. If a platform is already installed (a previous test init, or any code that triggered backend initialization), the call returns an error and the `.expect("platform already initialized")` panics. Slint allows exactly one platform initialization per process lifetime.
Solutions
- Restructure tests so the whole binary has one init: put multiple scenarios inside a single #[test] function, as the function's docs recommend.
- Use a shared `std::sync::Once` guard around the init call so it executes exactly once per process.
- Split tests into separate binaries (one #[test] per integration test file) so each process initializes the platform once.
- Alternatively call `init_integration_test_with_mock_time()`/`_with_system_time()`, which are designed for the same one-time role — but still only once.
Example fix
// before
#[test] fn a() { slint_testing::init_no_event_loop(); /* ok */ }
#[test] fn b() { slint_testing::init_no_event_loop(); /* panics */ }
// after: one init per process
static INIT: std::sync::Once = std::sync::Once::new();
fn ensure_init() {
INIT.call_once(|| slint_testing::init_no_event_loop());
}
#[test] fn a() { ensure_init(); /* ... */ }
#[test] fn b() { ensure_init(); /* ... */ } Defensive patterns
Strategy: validation
Validate before calling
use std::sync::Once;
static TEST_INIT: Once = Once::new();
pub fn ensure_testing_init() {
TEST_INIT.call_once(|| slint_testing::init_no_event_loop());
} Try / catch
// tolerate repeated init at call site
if TEST_INIT.is_completed() { return; }
slint_testing::init_no_event_loop(); Prevention
- Guard all testing-backend init behind a std::sync::Once
- Keep one #[test] function per integration test binary
- Never create Slint components before the testing backend init runs
- Avoid mixing doc tests and unit tests that each initialize the platform in one process
When it happens
Trigger: Calling `slint_testing::init_no_event_loop()` (or the related init_integration_test_* functions) more than once in the same process, e.g. multiple #[test] functions in one test binary, or after something else already created a window/backend.
Common situations: Integration test crates with several #[test] fns (each test binary runs them in one process); combining testing-backend init with a doc test; an earlier test created a Slint component before the init call, auto-initializing the platform.
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
- context shouldn't have been set before
- Could not load the slint-dev development binary
- no simulated native drag in flight
- run_until_complete's future isn't done
- slint_testing_use_native_popup called without testing…
AI-assisted analysis of slint-ui/slint@bb937076de (2026-09-16).
Data as JSON: /api/errors/d7c109bb9f8bf2cc.
Report an issue: GitHub.
Appendix: source
Thrown at internal/backends/testing/lib.rs:45
pub mod systest;
/// Initialize the testing backend without support for event loop.
/// This means that each test thread can use its own backend, but global functions that needs
/// an event loop such as `slint::invoke_from_event_loop` or `Timer`s won't work.
/// Must be called before any call that would otherwise initialize the rendering backend.
/// Calling it when the rendering backend is already initialized will panic.
///
/// Note that for animations and timers, the changes in the system time will be disregarded.
/// Instead, use [`mock_elapsed_time()`] to advance the simulate (mock) time Slint uses.
pub fn init_no_event_loop() {
i_slint_core::platform::set_platform(Box::new(testing_backend::TestingBackend::new(
testing_backend::TestingBackendOptions {
mock_time: true,
threading: false,
..Default::default()
},
)))
.expect("platform already initialized");
}
/// Initialize the testing backend with support for simple event loop.
/// This function can only be called once per process, so make sure to use integration
/// tests with only one `#[test]` function. (Or in a doc test)
/// Must be called before any call that would otherwise initialize the rendering backend.
/// Calling it when the rendering backend is already initialized will panic.
///
/// Note that for animations and timers, the changes in the system time will be disregarded.
/// Instead, use [`mock_elapsed_time()`] to advance the simulate (mock) time Slint uses.
pub fn init_integration_test_with_mock_time() {
i_slint_core::platform::set_platform(Box::new(testing_backend::TestingBackend::new(
testing_backend::TestingBackendOptions {
mock_time: true,
threading: true,
..Default::default()
},
)))View on GitHub (pinned to bb937076de)