{"record":{"id":"20a1c160960c9106","repo":"FyroxEngine/Fyrox","slug":"widget-node-handle-on-update-method-is-already","errorCode":null,"errorMessage":"Widget {node_handle} `on_update` method is already registered!","messagePattern":"Widget (.+?) `on_update` method is already registered!","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"fyrox-ui/src/lib.rs","lineNumber":673,"sourceCode":"    handle_os_event: FxHashSet<Handle<UiNode>>,\n}\n\nimpl WidgetMethodsRegistry {\n    fn register<T: Control + ?Sized>(&mut self, node: &T) {\n        let node_handle = node.handle();\n\n        if node.preview_messages && !self.preview_message.insert(node_handle) {\n            Log::warn(format!(\n                \"Widget {node_handle} `preview_message` method is already registered!\"\n            ));\n        }\n        if node.handle_os_events && !self.handle_os_event.insert(node_handle) {\n            Log::warn(format!(\n                \"Widget {node_handle} `handle_os_event` method is already registered!\"\n            ));\n        }\n        if node.need_update && !self.on_update.insert(node_handle) {\n            Log::warn(format!(\n                \"Widget {node_handle} `on_update` method is already registered!\"\n            ));\n        }\n    }\n\n    fn unregister<T: Control + ?Sized>(&mut self, node: &T) {\n        let node_handle = node.handle();\n\n        self.preview_message.remove(&node_handle);\n        self.on_update.remove(&node_handle);\n        self.handle_os_event.remove(&node_handle);\n    }\n}\n\n/// A set of switches that allows you to disable a particular step of UI update pipeline.\n#[derive(Clone, PartialEq, Eq, Default)]\npub struct UiUpdateSwitches {\n    /// A set of nodes that will be updated, everything else won't be updated.","sourceCodeStart":655,"sourceCodeEnd":691,"githubUrl":"https://github.com/FyroxEngine/Fyrox/blob/76c91aad8eca488ce527b1af707be8b3b24ad72d/fyrox-ui/src/lib.rs#L655-L691","documentation":"During widget registration the registry inserts the node handle into the on_update set when the widget's need_update flag is true. Inserting an already-present handle means the same widget is registered twice, producing this warning. It flags duplicate registration of an updatable widget; the registry prevents double updates but the call site has a bug.","triggerScenarios":"Calling WidgetMethodsRegistry::register (via the UI node registration flow) twice for a widget whose Control::need_update is true — e.g. re-inserting a node, builder double-registration, or plugin reload re-registering without unregistering.","commonSituations":"Widgets with per-frame update logic (Control::on_update) added to the UI twice; re-registering after a remove that skipped unregister; game code rebuilding UI without cleaning registry state.","solutions":["Register each widget exactly once; audit the add-node path for double calls.","Always pair register with unregister on widget removal so handles don't persist in the on_update set.","Add a registration guard/flag around repeated UI rebuilds.","If harmless in your flow, the warning can be tolerated, but fix the duplicate to avoid future routing bugs."],"exampleFix":"// before\nlet widget = MyWidgetBuilder::new(...).build(ctx);\nui.register(widget.clone());\nui.register(widget); // duplicate\n// after\nlet widget = MyWidgetBuilder::new(...).build(ctx);\nui.register(widget); // single registration","handlingStrategy":"validation","validationCode":"let newly = self.registered_update_handles.insert(node.handle());\nif newly { ui.register_widget(node); }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Ensure each updatable widget is registered exactly once.","Unregister on remove so the on_update set stays consistent.","Centralize UI registration in one function to avoid scattered duplicate calls.","On UI rebuild, reset registry state alongside widget handles."],"tags":["gui","duplicate-registration","lifecycle"],"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"}