{"record":{"id":"1d2a0fb41c85e901","repo":"yewstack/yew","slug":"global-document-not-set-1d2a0f","errorCode":null,"errorMessage":"global document not set","messagePattern":"global document not set","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"website/versioned_docs/version-0.22/concepts/basic-web-technologies/web-sys.mdx","lineNumber":182,"sourceCode":"\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\ntypes reminding us that some of these function calls have invariants that must be held, or otherwise will\ncause a panic in Rust. Another part of the verbosity is the calls to `JsCast` to cast into\ndifferent types so that you can call its specific methods.\n\n### Yew example\n\nIn Yew you will mostly be creating [`Callback`](concepts/function-components/callbacks.mdx)s to use in the\n[`html!`](concepts/html/introduction.mdx) macro so the example is going to use this approach instead of completely copying","sourceCodeStart":164,"sourceCodeEnd":200,"githubUrl":"https://github.com/yewstack/yew/blob/0e4a05472fac4e5fce1befe60fa4a1e43a36b6a3/website/versioned_docs/version-0.22/concepts/basic-web-technologies/web-sys.mdx#L164-L200","documentation":"This panic is `Document::new().expect(\"global document not set\")` in the web-sys guide. Despite the message, `web_sys::Document::new()` does not fetch the global document — it invokes the JS `Document` constructor. In engines or embeddings without that constructor it throws, and wasm-bindgen surfaces the thrown value as the `Err` this expect panics on; where the constructor exists it returns a brand-new empty document, which then guarantees the follow-up `get_element_by_id` expect (error 67) fails too. The global document must be obtained via `gloo::utils::document()` or `web_sys::window()?.document()?`.","triggerScenarios":"Running the example in an environment without a full browser DOM (web worker, SSR, minimal test harness) or an engine lacking the `Document` constructor; any code path that copies the guide's `Document::new()` line verbatim instead of using the global-document accessor.","commonSituations":"Copy-pasting the web-sys.mdx mousemove example into a Yew app that already depends on gloo; Trunk SSR builds; unit tests executed in Node without a DOM polyfill.","solutions":["Replace `Document::new()` with `gloo::utils::document()` — the guide's own portal example uses exactly this accessor","Or use the explicit form `web_sys::window().expect(\"no window\").document().expect(\"no document\")`","Keep DOM-touching code out of worker/SSR code paths (gate with `#[cfg(target_arch = \"wasm32\")]` and a browser feature check)"],"exampleFix":"// before\nDocument::new()\n    .expect(\"global document not set\")\n    .get_element_by_id(\"mousemoveme\")\n\n// after\nlet document = web_sys::window()\n    .and_then(|w| w.document())\n    .expect(\"no global window/document\");\ndocument.get_element_by_id(\"mousemoveme\")\n// or simply: gloo::utils::document().get_element_by_id(\"mousemoveme\")","handlingStrategy":"validation","validationCode":"fn global_document() -> Option<web_sys::Document> {\n    web_sys::window().and_then(|w| w.document())\n}\n\nmatch global_document() {\n    Some(doc) => { /* DOM work */ },\n    None => gloo::console::warn(\"no global document (worker/SSR?)\"),\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never use Document::new() to obtain the page document — it constructs a new empty document","Standardize on gloo::utils::document()/window() for DOM access across the codebase","Gate DOM-touching code so it cannot run in workers or SSR builds","Wrap document access in one helper so the fallback lives in a single place"],"tags":["web-sys","document","gloo","dom-api-misuse","panic"],"backgroundTag":"missing-dom-global","analyzedSha":"0e4a05472fac4e5fce1befe60fa4a1e43a36b6a3","analyzedAt":"2026-08-22T21:16:31.212Z","schemaVersion":2},"datasetVersion":"2026-08-23T01:17:44.959Z"}