yewstack/yew · error

Event should have a target when dispatched

Error message

Event should have a target when dispatched

What it means

This panic is the `.expect("Event should have a target when dispatched")` on `Event::target()` in Yew 0.23's events guide, same listing as 0.21/0.22. `Event::target()` returns `Option<EventTarget>`; the DOM permits targetless events (constructed but undispatched, or window-dispatched), and Yew hands the raw browser event to the `Callback<Event>`. A None target panics here. Real user-driven `change` events on the `<input>` always have a target, so this panic indicates synthetic or test-driven events.

Source

Thrown at website/versioned_docs/version-0.23/concepts/html/events.mdx:155

        Callback::from(move |e: Event| {
            // When events are created the target is undefined, it's only
            // when dispatched does the target get added.
            let target: Option<EventTarget> = e.target();
            // Events can bubble so this listener might catch events from child
            // elements which are not of type HtmlInputElement
            //highlight-next-line
            let input = target.and_then(|t| t.dyn_into::<HtmlInputElement>().ok());

            if let Some(input) = input {
                input_value_handle.set(input.value());
            }
        })
    };

    let on_dangerous_change = Callback::from(move |e: Event| {
        let target: EventTarget = e
            .target()
            .expect("Event should have a target when dispatched");
        // You must KNOW target is a HtmlInputElement, otherwise
        // the call to value would be Undefined Behaviour (UB).
        // Here we are sure that this is input element so we can convert it to the appropriate type without checking
        //highlight-next-line
        input_value_handle.set(target.unchecked_into::<HtmlInputElement>().value());
    });

    html! {
        <>
            <label for="cautious-input">
                { "My cautious input:" }
                <input onchange={on_cautious_change}
                    id="cautious-input"
                    type="text"
                    value={input_value.clone()}
                />
            </label>
            <label for="dangerous-input">

View on GitHub (pinned to 0e4a05472f)

Solutions

  1. Handle the Option: `let Some(target) = e.target() else { return; };`
  2. Prefer `e.target_dyn_into::<HtmlInputElement>()` (presence + type check, as the same guide teaches)
  3. Dispatch test events from the real input element

Example fix

// before
let target: EventTarget = e
    .target()
    .expect("Event should have a target when dispatched");
input_value_handle.set(target.unchecked_into::<HtmlInputElement>().value());

// after
if let Some(input) = e.target_dyn_into::<HtmlInputElement>() {
    input_value_handle.set(input.value());
}
Defensive patterns

Strategy: type-guard

Validate before calling

let on_dangerous_change = Callback::from(move |e: Event| {
    let Some(target) = e.target() else {
        return;
    };
    let _ = target;
});

Type guard

use web_sys::{Event, HtmlInputElement};

fn input_target(e: &Event) -> Option<HtmlInputElement> {
    e.target_dyn_into::<HtmlInputElement>()
}

Prevention

When it happens

Trigger: Tests calling the `on_dangerous_change` callback with an `Event::new(...)` value (target None); dispatching `change` on `window` via `dispatchEvent`; retargeted events from shadow-DOM test utilities.

Common situations: Copy-pasting the events.mdx `unchecked_into` recipe (line ~155) from the 0.23 docs; headless test suites synthesizing input events.

Related errors


AI-assisted analysis of yewstack/yew@0e4a05472f (2026-08-22). Data as JSON: /api/errors/a2e3c250cd2a06a4. Report an issue: GitHub.