kitao/pyxel · critical
Pyxel not initialized
Error message
Pyxel not initialized
What it means
This panic comes from the `pyxel()` accessor in pyxel-core, which unwraps the thread-local `Option<Pyxel>` singleton. It fires whenever any Pyxel API is used before the singleton has been installed by `init`. The library guards all state access through this accessor, so an uninitialized access cannot be recovered from — it panics instead of returning a Result.
Source
Thrown at crates/pyxel-core/src/pyxel.rs:48
pub(crate) system: System,
pub(crate) resource: Resource,
pub(crate) input: Input,
pub(crate) graphics: Option<Graphics>,
}
static IS_INITIALIZED: AtomicBool = AtomicBool::new(false);
// Singleton
thread_local! {
static PYXEL: &'static RefCell<Option<Pyxel>> =
Box::leak(Box::new(RefCell::new(None)));
}
pub fn pyxel() -> RefMut<'static, Pyxel> {
PYXEL.with(|instance| {
let instance: &'static RefCell<Option<Pyxel>> = instance;
RefMut::map(instance.borrow_mut(), |instance| {
instance.as_mut().expect("Pyxel not initialized")
})
})
}
fn set_pyxel(instance: Pyxel) {
// The leaked RefCell keeps the owner address stable through Python module
// cleanup; replace its value only when the next initialization is ready.
PYXEL.with(|current| *current.borrow_mut() = Some(instance));
}
// Lifecycle callbacks
type ResetCallback = Option<Box<dyn FnMut(Option<String>) + Send>>;
thread_local! {
static RESET_CALLBACK: &'static RefCell<ResetCallback> =
Box::leak(Box::new(RefCell::new(None)));
}View on GitHub (pinned to 50f9bd7778)
Solutions
- Call `pyxel::init(width, height, ...)` before any other Pyxel API call.
- Ensure all Pyxel calls run on the same thread that called init (the singleton is thread-local).
- If tearing down and re-initializing, re-run init before further API use.
- Gate API usage behind an `is_initialized` check / IS_INITIALIZED flag in wrapper code.
Example fix
// before let img = pyxel_core::graphics::image(0); // panics: Pyxel not initialized // after pyxel::init(160, 120, None, None, None, None); let img = pyxel_core::graphics::image(0);
Defensive patterns
Strategy: try-catch
Validate before calling
// Rust: guard calls behind init state
fn ensure_pyxel_ready() -> Result<(), String> {
if !IS_INITIALIZED.load(std::sync::atomic::Ordering::Acquire) {
return Err("call pyxel::init() before using the API".into());
}
Ok(())
} Try / catch
// Rust panics cannot be caught by Result; use catch_unwind at the boundary
let result = std::panic::catch_unwind(|| {
pyxel_core::graphics::image(0)
});
match result {
Ok(img) => use_image(img),
Err(_) => eprintln!("Pyxel API used before init()"),
} Prevention
- Always call pyxel::init() as the first Pyxel call in main() or the module entry point.
- Never call Pyxel APIs from threads other than the one that ran init (thread-local singleton).
- Do not call Pyxel functions in static/const initializers or before main.
- After quitting/re-init, re-run init before any further API use.
When it happens
Trigger: Calling any pyxel-core/pyxel API (graphics, audio, input, tilemap, etc.) that internally calls `pyx()`/`pyxel()` before `pyxel::init(...)` has completed, or after init/quit teardown has cleared the instance. Also calling from a different thread than the one where init ran, since the singleton is thread-local.
Common situations: Calling a Pyxel function at module top-level or in a static initializer before init; calling Pyxel APIs from a worker thread; calling APIs after the app has quit and cleanup ran; forgetting init in a test harness that exercises drawing/audio helpers directly.
Related errors
- canvas dimensions are too large
- image dimensions are too large
- tilemap dimensions are too large
- pyxel.flip is not supported on Pyxel Web
- Failed to open file '{path}'
AI-assisted analysis of kitao/pyxel@50f9bd7778 (2026-09-03).
Data as JSON: /api/errors/8d1c26d5be7de838.
Report an issue: GitHub.