{"record":{"id":"6815d8728ee99f54","repo":"yewstack/yew","slug":"event-target-should-be-of-type-htmlelement-6815d8","errorCode":null,"errorMessage":"event target should be of type HtmlElement","messagePattern":"event target should be of type HtmlElement","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"website/versioned_docs/version-0.22/concepts/basic-web-technologies/web-sys.mdx","lineNumber":174,"sourceCode":"features = [\n    \"console\",\n    \"Document\",\n    \"HtmlElement\",\n    \"MouseEvent\",\n    \"DomRect\",\n]\n```\n\n```rust ,no_run\nuse wasm_bindgen::{prelude::Closure, JsCast};\nuse web_sys::{console, Document, HtmlElement, MouseEvent};\n\nlet mousemove = Closure::<dyn Fn(MouseEvent)>::wrap(Box::new(|e| {\n    let rect = e\n        .target()\n        .expect(\"mouse event doesn't have a target\")\n        .dyn_into::<HtmlElement>()\n        .expect(\"event target should be of type HtmlElement\")\n        .get_bounding_client_rect();\n    let x = (e.client_x() as f64) - rect.left();\n    let y = (e.client_y() as f64) - rect.top();\n    console::log_1(&format!(\"Left? : {} ; Top? : {}\", x, y).into());\n}));\n\nDocument::new()\n    .expect(\"global document not set\")\n    .get_element_by_id(\"mousemoveme\")\n    .expect(\"element with id `mousemoveme` not present\")\n    .unchecked_into::<HtmlElement>()\n    .set_onmousemove(mousemove.as_ref().dyn_ref());\n\n// we now need to save the `mousemove` Closure so that when\n// this event fires the closure is still in memory.\n```\n\nThis version is much more verbose, but you will probably notice part of that is because of failure","sourceCodeStart":156,"sourceCodeEnd":192,"githubUrl":"https://github.com/yewstack/yew/blob/0e4a05472fac4e5fce1befe60fa4a1e43a36b6a3/website/versioned_docs/version-0.22/concepts/basic-web-technologies/web-sys.mdx#L156-L192","documentation":"This panic is `.dyn_into::<HtmlElement>().expect(\"event target should be of type HtmlElement\")` in the web-sys mousemove example. `JsCast::dyn_into` returns `Result<HtmlElement, EventTarget>`; it errors when the target's underlying JS value is not an `HtmlElement` instance. The example assumes `e.target()` is the tracked `#mousemoveme` element, but the target is the deepest node under the pointer: attaching the listener to `document`/`window` makes the target a Document (not HtmlElement), and hovering SVG children yields `SvgElement`, which is also not `HtmlElement`.","triggerScenarios":"Attaching `onmousemove` to `document` or `window` instead of an element (target becomes Document/Window); the pointer moving over an `<svg>`/`<math>` descendant, making the target an `SvgElement`/`MathMLElement`; synthetic events dispatched on document in tests.","commonSituations":"Adapting the web-sys.mdx coordinate snippet to track the whole page (so developers bind on `document`); graphics-heavy apps with SVG icons inside the tracked region; headless tests dispatching on non-element nodes.","solutions":["Replace `dyn_into(...).expect(...)` with `target.dyn_ref::<HtmlElement>()` inside an `if let` and skip non-element targets","Use `e.current_target()` instead of `e.target()` — it is always the element you attached the handler to, so the cast is sound","If you intentionally listen on document, branch on the concrete type: `match target.dyn_into() { Ok(el) => ..., Err(_) => ... }`"],"exampleFix":"// before\n.dyn_into::<HtmlElement>()\n.expect(\"event target should be of type HtmlElement\")\n.get_bounding_client_rect();\n\n// after\nlet rect = e\n    .current_target()\n    .dyn_into::<HtmlElement>()\n    .ok()?\n    .get_bounding_client_rect();\n// or, when you really need the hit element:\n// if let Some(el) = e.target().and_then(|t| t.dyn_ref::<HtmlElement>().map(|el| el.get_bounding_client_rect())) { ... }","handlingStrategy":"type-guard","validationCode":"let rect = {\n    let t = e.current_target(); // the element this handler is bound to\n    if !t.is_instance_of::<web_sys::HtmlElement>() {\n        return;\n    }\n    t.unchecked_ref::<web_sys::HtmlElement>().get_bounding_client_rect()\n};","typeGuard":"use wasm_bindgen::JsCast;\nuse web_sys::{EventTarget, HtmlElement};\n\nfn is_html_element(t: &EventTarget) -> bool {\n    t.is_instance_of::<HtmlElement>()\n}","tryCatchPattern":null,"preventionTips":["Prefer current_target() over target() when you need the element the listener is attached to","Use dyn_ref::<HtmlElement>() + if-let instead of dyn_into().expect()","Remember SVG/MathML hit targets are SvgElement/MathMLElement, not HtmlElement","When binding to document or window, branch on the concrete target type instead of assuming HtmlElement"],"tags":["web-sys","jscast","events","type-mismatch","panic"],"backgroundTag":"runtime-type-cast-failed","analyzedSha":"0e4a05472fac4e5fce1befe60fa4a1e43a36b6a3","analyzedAt":"2026-08-22T21:16:31.212Z","schemaVersion":2},"datasetVersion":"2026-08-23T01:17:44.959Z"}