{"record":{"id":"8d1c26d5be7de838","repo":"kitao/pyxel","slug":"pyxel-not-initialized","errorCode":null,"errorMessage":"Pyxel not initialized","messagePattern":"Pyxel not initialized","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"crates/pyxel-core/src/pyxel.rs","lineNumber":48,"sourceCode":"    pub(crate) system: System,\n    pub(crate) resource: Resource,\n    pub(crate) input: Input,\n    pub(crate) graphics: Option<Graphics>,\n}\n\nstatic IS_INITIALIZED: AtomicBool = AtomicBool::new(false);\n\n// Singleton\nthread_local! {\n    static PYXEL: &'static RefCell<Option<Pyxel>> =\n        Box::leak(Box::new(RefCell::new(None)));\n}\n\npub fn pyxel() -> RefMut<'static, Pyxel> {\n    PYXEL.with(|instance| {\n        let instance: &'static RefCell<Option<Pyxel>> = instance;\n        RefMut::map(instance.borrow_mut(), |instance| {\n            instance.as_mut().expect(\"Pyxel not initialized\")\n        })\n    })\n}\n\nfn set_pyxel(instance: Pyxel) {\n    // The leaked RefCell keeps the owner address stable through Python module\n    // cleanup; replace its value only when the next initialization is ready.\n    PYXEL.with(|current| *current.borrow_mut() = Some(instance));\n}\n\n// Lifecycle callbacks\n\ntype ResetCallback = Option<Box<dyn FnMut(Option<String>) + Send>>;\n\nthread_local! {\n    static RESET_CALLBACK: &'static RefCell<ResetCallback> =\n        Box::leak(Box::new(RefCell::new(None)));\n}","sourceCodeStart":30,"sourceCodeEnd":66,"githubUrl":"https://github.com/kitao/pyxel/blob/50f9bd77780c993aca62b5b221766bde5791081d/crates/pyxel-core/src/pyxel.rs#L30-L66","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nlet img = pyxel_core::graphics::image(0); // panics: Pyxel not initialized\n// after\npyxel::init(160, 120, None, None, None, None);\nlet img = pyxel_core::graphics::image(0);","handlingStrategy":"try-catch","validationCode":"// Rust: guard calls behind init state\nfn ensure_pyxel_ready() -> Result<(), String> {\n    if !IS_INITIALIZED.load(std::sync::atomic::Ordering::Acquire) {\n        return Err(\"call pyxel::init() before using the API\".into());\n    }\n    Ok(())\n}","typeGuard":null,"tryCatchPattern":"// Rust panics cannot be caught by Result; use catch_unwind at the boundary\nlet result = std::panic::catch_unwind(|| {\n    pyxel_core::graphics::image(0)\n});\nmatch result {\n    Ok(img) => use_image(img),\n    Err(_) => eprintln!(\"Pyxel API used before init()\"),\n}","preventionTips":["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."],"tags":["rust","panic","initialization","singleton","thread-local"],"backgroundTag":"library-not-initialized","analyzedSha":"50f9bd77780c993aca62b5b221766bde5791081d","analyzedAt":"2026-09-03T10:27:43.285Z","contentChangedAt":"2026-09-03T10:27:43.285Z","schemaVersion":2},"datasetVersion":"2026-09-10T17:17:09.494Z"}