yewstack/yew · warning
mouse event doesn't have a target
Error message
mouse event doesn't have a target
What it means
The web-sys tutorial expects e.target() inside a mousemove handler attached with set_onmousemove. Real browser mousemove events always carry a target, so in production this expect can only fire for MouseEvent objects synthesized by application code or tests without a target. The snippet is illustrative; shipping code should not assume target presence.
Source
Thrown at website/versioned_docs/version-0.21/concepts/basic-web-technologies/web-sys.mdx:173
version = "0.3"
# We need to enable all the web-sys features we want to use!
features = [
"console",
"Document",
"HtmlElement",
"MouseEvent",
"DomRect",
]
```
```rust ,no_run
use wasm_bindgen::{prelude::Closure, JsCast};
use web_sys::{console, Document, HtmlElement, MouseEvent};
let mousemove = Closure::<dyn Fn(MouseEvent)>::wrap(Box::new(|e| {
let rect = e
.target()
.expect("mouse event doesn't have a target")
.dyn_into::<HtmlElement>()
.expect("event target should be of type HtmlElement")
.get_bounding_client_rect();
let x = (e.client_x() as f64) - rect.left();
let y = (e.client_y() as f64) - rect.top();
console::log_1(&format!("Left? : {} ; Top? : {}", x, y).into());
}));
Document::new()
.expect("global document not set")
.get_element_by_id("mousemoveme")
.expect("element with id `mousemoveme` not present")
.unchecked_into::<HtmlElement>()
.set_onmousemove(mousemove.as_ref().dyn_ref());
// we now need to save the `mousemove` Closure so that when
// this event fires the closure is still in memory.
```View on GitHub (pinned to 0e4a05472f)
Solutions
- Use e.current_target() - the element the listener is bound to - which is always present during dispatch
- Guard with if let Some(target) = e.target()
- When synthesizing events in tests, dispatch them from a real element so target is set
- Treat the snippet as a starting point and add Option handling before shipping
Example fix
// before
let rect = e.target()
.expect("mouse event doesn't have a target")
.dyn_into::<HtmlElement>().unwrap()
.get_bounding_client_rect();
// after: the element the listener is attached to - no Option panic
let rect = e.current_target()
.dyn_into::<HtmlElement>()
.expect("listener is bound to an HtmlElement")
.get_bounding_client_rect(); Defensive patterns
Strategy: type-guard
Type guard
fn mousemove_element(e: &web_sys::MouseEvent) -> Option<web_sys::Element> {
e.current_target().and_then(|t| t.dyn_into::<web_sys::Element>().ok())
} Prevention
- Bind geometry math to current_target() (the element you attached the listener to), not target()
- Handle the Option from target() instead of expecting it
- Dispatch synthetic MouseEvents from real elements in tests
When it happens
Trigger: Manually constructed/dispatched MouseEvents reaching this handler (tests, automation or replay tooling calling dispatchEvent on bare events); reusing the tutorial listener for other event types whose target can be null.
Common situations: Simulating pointer movement in tests; automation scripts synthesizing events; copy-pasted tutorial code later pointed at different event sources.
Related errors
- I'm sure this event has a target!
- event target should be of type HtmlElement
- global document not set
- I'm sure this event has a target!
- mouse event doesn't have a target
AI-assisted analysis of yewstack/yew@0e4a05472f (2026-08-22).
Data as JSON: /api/errors/dde4de69a9f7910c.
Report an issue: GitHub.