FyroxEngine/Fyrox · warning
Widget `handle_os_event` method is already registered!
Error message
Widget {node_handle} `handle_os_event` method is already registered! What it means
During widget registration the registry inserts the node handle into the handle_os_event set when the widget's handle_os_events flag is true. If the handle is already in the set the widget is being registered a second time, and this warning is logged. It indicates duplicate registration of a widget that handles OS events; behavior is otherwise unaffected.
Solutions
- Ensure register() is called only once per widget instance.
- Call unregister() on widget removal so re-adds don't collide with stale set entries.
- Deduplicate your registration code path (e.g. use a HashSet or builder state to check before registering).
- Ignore if benign, but resolve to keep method routing correct.
Example fix
// before
fn on_rebuild(&mut self, ui) {
self.register(ui); // runs every rebuild for an already-registered widget
}
// after
fn on_rebuild(&mut self, ui) {
if !self.is_registered {
self.register(ui);
self.is_registered = true;
}
} Defensive patterns
Strategy: validation
Validate before calling
let newly = self.registered_os_event_handles.insert(node.handle());
if newly { ui.register_widget(node); } Prevention
- Keep registration idempotent in rebuild/reload paths.
- Unregister widgets before re-registering.
- Only enable handle_os_events on widgets that truly need it.
- Audit custom Control impls for double registration calls.
When it happens
Trigger: Calling WidgetMethodsRegistry::register (via the UI's node registration path) twice for the same widget whose Control::handle_os_events returns true — e.g. re-adding a node or double-invoked registration code.
Common situations: Custom widgets that respond to keyboard/mouse OS events being re-registered by plugin reload or builder misuse; adding the same node handle to the UI graph twice.
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
- Widget `preview_message` method is already registered!
- Widget `on_update` method is already registered!
- There's no message sender for shared handle
- Window name is empty, wrong widget will be used as a tile…
- Floating window name is empty, wrong widget will be used as…
AI-assisted analysis of FyroxEngine/Fyrox@76c91aad8e (2026-09-10).
Data as JSON: /api/errors/b14d6e89fdc0256e.
Report an issue: GitHub.
Appendix: source
Thrown at fyrox-ui/src/lib.rs:668
#[derive(Default, PartialEq, Debug, Clone)]
struct WidgetMethodsRegistry {
preview_message: FxHashSet<Handle<UiNode>>,
on_update: FxHashSet<Handle<UiNode>>,
handle_os_event: FxHashSet<Handle<UiNode>>,
}
impl WidgetMethodsRegistry {
fn register<T: Control + ?Sized>(&mut self, node: &T) {
let node_handle = node.handle();
if node.preview_messages && !self.preview_message.insert(node_handle) {
Log::warn(format!(
"Widget {node_handle} `preview_message` method is already registered!"
));
}
if node.handle_os_events && !self.handle_os_event.insert(node_handle) {
Log::warn(format!(
"Widget {node_handle} `handle_os_event` method is already registered!"
));
}
if node.need_update && !self.on_update.insert(node_handle) {
Log::warn(format!(
"Widget {node_handle} `on_update` method is already registered!"
));
}
}
fn unregister<T: Control + ?Sized>(&mut self, node: &T) {
let node_handle = node.handle();
self.preview_message.remove(&node_handle);
self.on_update.remove(&node_handle);
self.handle_os_event.remove(&node_handle);
}
}View on GitHub (pinned to 76c91aad8e)