FyroxEngine/Fyrox · warning

There's no message sender for shared handle

Error message

There's no message sender for shared handle {}. The object won't be destroyed.

What it means

RcUiNodeHandle is a shared handle that, when dropped, sends a Remove widget message back to the UI via a stored message sender so the widget is destroyed. If the sender is None (handle created without a sender), the widget cannot be scheduled for destruction, the node leaks in the UI, and this warning is logged.

Solutions

  1. Create/clone the shared handle through the API path that supplies a sender so Drop can send WidgetMessage::Remove.
  2. Send WidgetMessage::Remove manually for the handle if you know the UI instance.
  3. Verify the UI that owns the widget is still alive when the handle drops; teardown order may invalidate the sender path.
  4. If leaking is intentional, ignore the warning or manage the widget lifetime explicitly.

Example fix

// before
let handle = RcUiNodeHandle::new(node_handle, None); // no sender -> leak on drop
// after
let handle = RcUiNodeHandle::new(node_handle, Some(ui_sender.clone()));
// or, on cleanup:
ui.send_message(WidgetMessage::remove(node_handle));
Defensive patterns

Strategy: fallback

Validate before calling

// Before dropping, ensure the widget will be removed
if handle_needs_manual_cleanup {
    ui.send_message(WidgetMessage::remove(node_handle));
}

Prevention

When it happens

Trigger: Dropping an RcUiNodeHandle whose inner RcUiNodeHandleInner was constructed with sender: None — i.e. the handle was created through an API path that doesn't supply a UiMessage sender, then the last reference is dropped.

Common situations: Storing RcUiNodeHandles taken from widget contexts/builders where no sender is available, then letting the handle drop and noticing the widget still exists in the UI; holding handles across UI teardown so the sender is gone.

Understand the failure class

Background: "not installed", "pip install", "required for": how missing-dependency errors surface across open-source libraries — this error's family across 34 libraries.

Related errors


AI-assisted analysis of FyroxEngine/Fyrox@76c91aad8e (2026-09-10). Data as JSON: /api/errors/fde49b8674e5becb. Report an issue: GitHub.

Appendix: source

Thrown at fyrox-ui/src/lib.rs:405

            self.sender = Some(
                visitor
                    .blackboard
                    .get::<Sender<UiMessage>>()
                    .expect("Ui message sender must be provided for correct deserialization!")
                    .clone(),
            );
        }

        Ok(())
    }
}

impl Drop for RcUiNodeHandleInner {
    fn drop(&mut self) {
        if let Some(sender) = self.sender.as_ref() {
            let _ = sender.send(UiMessage::for_widget(self.handle, WidgetMessage::Remove));
        } else {
            Log::warn(format!(
                "There's no message sender for shared handle {}. The object \
            won't be destroyed.",
                self.handle
            ))
        }
    }
}

/// Reference counted handle to a widget. It is used to automatically destroy the widget it points
/// to when the reference counter reaches zero. Its main usage in the library is to store handles
/// to context menus that could be shared across multiple widgets.
#[derive(Clone, Default, Visit, Reflect)]
#[reflect(type_uuid = "9111a53b-05dc-4c75-aab1-71d5b1c93311")]
pub struct RcUiNodeHandle(Arc<Mutex<RcUiNodeHandleInner>>);

impl Debug for RcUiNodeHandle {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        let handle = self.0.safe_lock().handle;

View on GitHub (pinned to 76c91aad8e)