{"record":{"id":"81eb0a79648c9c91","repo":"yewstack/yew","slug":"global-document-not-set-81eb0a","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.23/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: MouseEvent| {\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.23/concepts/basic-web-technologies/web-sys.mdx#L164-L200","documentation":"This panic is `Document::new().expect(\"global document not set\")` in Yew 0.23's web-sys guide. `web_sys::Document::new()` calls the JS `Document` constructor; it is not the global-document accessor the message implies. In DOM-less environments (workers, SSR) or engines without the constructor it throws, and wasm-bindgen converts the thrown value into the `Err` that this expect panics on. Where the constructor works it yields a new empty document, which then makes the following `get_element_by_id(\"mousemoveme\")` expect (error 76) inevitable.","triggerScenarios":"Executing the example code where the JS `Document` constructor throws or no DOM exists (web worker, SSR, Node test without DOM polyfill); copying the guide line verbatim instead of using a global-document accessor.","commonSituations":"Copy-pasting the web-sys.mdx example into a Yew 0.23 app that already ships gloo; unit tests under `wasm-bindgen-test` in Node; Trunk SSR builds.","solutions":["Use `gloo::utils::document()` to obtain the live global document","Or `web_sys::window().and_then(|w| w.document())` with explicit expects on window/document presence","Keep DOM access out of worker/SSR code paths"],"exampleFix":"// before\nDocument::new()\n    .expect(\"global document not set\")\n    .get_element_by_id(\"mousemoveme\")\n\n// after\ngloo::utils::document().get_element_by_id(\"mousemoveme\")\n// equivalent explicit form:\n// web_sys::window().and_then(|w| w.document()).expect(\"no global document\")","handlingStrategy":"validation","validationCode":"fn global_document() -> Option<web_sys::Document> {\n    web_sys::window().and_then(|w| w.document())\n}\n\nif global_document().is_none() {\n    gloo::console::warn(\"no global document — skipping DOM setup\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Document::new() creates a new empty document — never use it to reach page elements","Use gloo::utils::document() as the single global-document accessor","Keep DOM code out of worker and SSR paths via cfg/feature gates","Codematch for Document::new() in review — it is almost always a copy-paste from this guide"],"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"}