{"record":{"id":"4f0f72f8cb8bb098","repo":"FyroxEngine/Fyrox","slug":"cannot-obtain-a-reference-to-the-plugin-because-i","errorCode":null,"errorMessage":"Cannot obtain a reference to the plugin, because it is unloaded!","messagePattern":"Cannot obtain a reference to the plugin, because it is unloaded!","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"fyrox-impl/src/plugin/dylib.rs","lineNumber":294,"sourceCode":"\n        Ok(())\n    }\n}\n\n/// Actual state of a dynamic plugin.\nenum PluginState {\n    /// Unloaded plugin.\n    Unloaded,\n    /// Loaded plugin.\n    Loaded(DyLibHandle),\n}\n\nimpl PluginState {\n    /// Tries to interpret the state as [`Self::Loaded`], panics if the plugin is unloaded.\n    pub fn as_loaded_ref(&self) -> &DyLibHandle {\n        match self {\n            PluginState::Unloaded => {\n                panic!(\"Cannot obtain a reference to the plugin, because it is unloaded!\")\n            }\n            PluginState::Loaded(dynamic) => dynamic,\n        }\n    }\n\n    /// Tries to interpret the state as [`Self::Loaded`], panics if the plugin is unloaded.\n    pub fn as_loaded_mut(&mut self) -> &mut DyLibHandle {\n        match self {\n            PluginState::Unloaded => {\n                panic!(\"Cannot obtain a reference to the plugin, because it is unloaded!\")\n            }\n            PluginState::Loaded(dynamic) => dynamic,\n        }\n    }\n}\n\nfn try_copy_library(source_lib_path: &Path, lib_path: &Path) -> Result<(), String> {\n    info!(","sourceCodeStart":276,"sourceCodeEnd":312,"githubUrl":"https://github.com/FyroxEngine/Fyrox/blob/76c91aad8eca488ce527b1af707be8b3b24ad72d/fyrox-impl/src/plugin/dylib.rs#L276-L312","documentation":"PluginState::as_loaded_ref returns a reference to the DyLibHandle only when the plugin is in the Loaded state. If the dynamic library was unloaded (PluginState::Unloaded), the plugin's code is no longer mapped, so the method panics rather than return a dangling reference.","triggerScenarios":"Calling plugin.as_loaded_ref() (via DynamicPlugin/PluginState) after unload() was called, or constructing a state as Unloaded and reading it.","commonSituations":"Accessing the plugin during/after hot-reload unload; plugin reload racing with a render/update call; forgetting reload() before use.","solutions":["Call as_loaded_ref only while the plugin is loaded; reload() first if it was unloaded","Check the PluginState enum (match on PluginState::Loaded) before access","Synchronize hot-reload unloading with the frame loop so no code touches the plugin while unloaded"],"exampleFix":"// before\nlet iface = plugin.as_loaded_ref();\n// after\nif let PluginState::Loaded(handle) = plugin.state() {\n    let iface = handle.plugin();\n}","handlingStrategy":"type-guard","validationCode":"let usable = !matches!(plugin.state(), PluginState::Unloaded);","typeGuard":"fn loaded(p: &PluginState) -> Option<&DyLibHandle> { if let PluginState::Loaded(d) = p { Some(d) } else { None } }","tryCatchPattern":null,"preventionTips":["Synchronize unload/reload with the frame loop","Check is_loaded before access","Never hold plugin references across unload"],"tags":["dylib","plugins","state","panic"],"backgroundTag":"invalid-state-transition","analyzedSha":"76c91aad8eca488ce527b1af707be8b3b24ad72d","analyzedAt":"2026-09-10T16:04:01.633Z","contentChangedAt":"2026-09-10T16:04:01.633Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}