linebender/druid · error

command must carry a ContextMenu .

Error message

{} command must carry a ContextMenu<application state>.

What it means

When druid's AppDelegate/handler processes the SHOW_CONTEXT_MENU command, the command's payload must be a `ContextMenu<application state>` object. If the command arrives without such a payload (wrong type or none at all), the downcast fails and the handler panics, since a context menu cannot be shown without its menu structure.

Solutions

  1. Use the built-in helper `ctx.show_context_menu(menu, pos)` (or `show_context_menu` on the appropriate context) rather than submitting sys_cmd::SHOW_CONTEXT_MENU manually
  2. If submitting manually, attach the payload: `.to(...)` is not enough — use a command that carries `ContextMenu<T>`, e.g. via the helper, so the downcast succeeds
  3. Ensure the ContextMenu was created for the same application state type `T` as the running app

Example fix

// before
ctx.submit_command(Command::new(sys_cmd::SHOW_CONTEXT_MENU, None, ctx.window_id()));
// after
ctx.show_context_menu(menu, ctx.to_point(pos)); // payload wired correctly
Defensive patterns

Strategy: validation

Validate before calling

// Verify payload type before submitting a SHOW_CONTEXT_MENU command manually
let cmd = Command::new(
    sys_cmd::SHOW_CONTEXT_MENU,
    Some(Box::new(ContextMenu::new(menu, pos))), // payload must be ContextMenu<T>
    ctx.window_id(),
);
ctx.submit_command(cmd);

Prevention

When it happens

Trigger: Submitting the `sys_cmd::SHOW_CONTEXT_MENU` command with `to(...)` but no payload, or with a payload that is not `ContextMenu<T>` (e.g. a raw Menu, wrong generic type, or a different struct).

Common situations: Hand-crafting the SHOW_CONTEXT_MENU command instead of using the `ctx.show_context_menu(menu)` helper; changing the application's state type `T` so an older payload no longer downcasts; passing `ContextMenu<OtherState>` created under a different state type.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


AI-assisted analysis of linebender/druid@0f8b1195e4 (2026-09-10). Data as JSON: /api/errors/7d5317d64ca206d4. Report an issue: GitHub.

Appendix: source

Thrown at druid/src/win_handler.rs:447

        if let Some(win) = self.windows.get_mut(source_id) {
            win.event(&mut self.command_queue, event, &mut self.data, &self.env)
        } else {
            Handled::No
        }
    }

    fn show_context_menu(&mut self, window_id: WindowId, cmd: &Command) {
        if let Some(win) = self.windows.get_mut(window_id) {
            match cmd
                .get_unchecked(sys_cmd::SHOW_CONTEXT_MENU)
                .take()
                .and_then(|b| b.downcast::<ContextMenu<T>>().ok())
            {
                Some(menu) => {
                    win.show_context_menu(menu.menu, menu.location, &self.data, &self.env)
                }
                None => panic!(
                    "{} command must carry a ContextMenu<application state>.",
                    sys_cmd::SHOW_CONTEXT_MENU
                ),
            }
        }
    }

    fn do_update(&mut self) {
        // we send `update` to all windows, not just the active one:
        for window in self.windows.iter_mut() {
            window.update(&mut self.command_queue, &self.data, &self.env);
            if let Some(focus_change) = window.ime_focus_change.take() {
                // we need to call this outside of the borrow, so we create a
                // closure that takes the correct window handle. yes, it feels
                // weird.
                let handle = window.handle.clone();
                let f = Box::new(move || handle.set_focused_text_field(focus_change));
                self.ime_focus_change = Some(f);

View on GitHub (pinned to 0f8b1195e4)