leptos-rs/leptos · error

event.target not found

Error message

event.target not found

What it means

Renderer::event_target reads ev.target() off the underlying web_sys::Event and panics if it is None. Per DOM spec target is usually present, but for events that have not been dispatched or synthetic/manually constructed events it can be missing, so the library panics to surface the invalid event.

Source

Thrown at tachys/src/renderer/dom.rs:362

                        cb.as_ref().unchecked_ref(),
                        true
                    ),
                    &el,
                    "removeEventListener"
                )
            });
            move || cb()
        })
    }

    pub fn event_target<T>(ev: &Event) -> T
    where
        T: CastFrom<Element>,
    {
        let el = ev
            .unchecked_ref::<web_sys::Event>()
            .target()
            .expect("event.target not found")
            .unchecked_into::<Element>();
        T::cast_from(el).expect("incorrect element type")
    }

    pub fn add_event_listener_delegated(
        el: &Element,
        name: Cow<'static, str>,
        delegation_key: Cow<'static, str>,
        cb: Box<dyn FnMut(Event)>,
    ) -> RemoveEventHandler<Element> {
        let cb = Closure::wrap(cb);
        let key = intern(&delegation_key);
        or_debug!(
            js_sys::Reflect::set(el, &JsValue::from_str(key), cb.as_ref()),
            el,
            "set property"
        );

View on GitHub (pinned to 32d20f6c9d)

Solutions

  1. Only call event_target inside a real listener callback with a dispatched event
  2. Check ev.target() yourself and use a fallback (e.g. current_target) when None
  3. In tests, create the event via dispatched dispatch_event on a real element
  4. For delegated listeners, prefer accessing the event target through the delegation machinery provided by the renderer

Example fix

// before
let el: HtmlElement<MyEl> = renderer.event_target::<MyEl>(&synthetic_event); // panics
// after
if let Some(t) = synthetic_event.target() {
    let el = MyEl::cast_from(t.unchecked_into()).unwrap_or_default();
}
Defensive patterns

Strategy: validation

Validate before calling

fn event_has_target(ev: &web_sys::Event) -> bool { ev.target().is_some() }
// only call event_target for dispatched events inside live listeners

Type guard

fn target_of(ev: &web_sys::Event) -> Option<web_sys::Element> {
    ev.target().map(|t| t.unchecked_into::<web_sys::Element>())
}

Try / catch

// pre-check instead of catching the panic:
if let Some(t) = ev.target() {
    let el = t.unchecked_into::<Element>();
    // proceed with cast_from
}

Prevention

When it happens

Trigger: Calling event_target with an event whose target is None: manually constructed/dispatched events without a target, events fetched after dispatch teardown, or passing a non-Event object that unchecked_ref misinterprets.

Common situations: Unit tests invoking handlers with fabricated Event objects; custom event delegation code reusing stale events; calling event_target outside an actual listener callback.

Related errors


AI-assisted analysis of leptos-rs/leptos@32d20f6c9d (2026-09-01). Data as JSON: /api/errors/6a4f911583c2bd14. Report an issue: GitHub.