{"record":{"id":"8bd6b5384b5544a7","repo":"yewstack/yew","slug":"global-document-not-set","errorCode":null,"errorMessage":"global document not set","messagePattern":"global document not set","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"website/versioned_docs/version-0.21/concepts/basic-web-technologies/web-sys.mdx","lineNumber":183,"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":165,"sourceCodeEnd":201,"githubUrl":"https://github.com/yewstack/yew/blob/0e4a05472fac4e5fce1befe60fa4a1e43a36b6a3/website/versioned_docs/version-0.21/concepts/basic-web-technologies/web-sys.mdx#L165-L201","documentation":"The tutorial constructs a Document via Document::new(), which maps to the JS Document constructor - browsers reject constructing documents this way (illegal constructor), and the binding is unavailable in non-window environments, so the expect fires. Despite the message, you almost never want a new document: you want the page's existing global document.","triggerScenarios":"Running the doc snippet verbatim in a browser (new Document() throws immediately); calling DOM bindings from a worker or other environment where no global document exists.","commonSituations":"Copy-pasting the tutorial into a real app; code shared between browser and worker/server contexts without environment checks.","solutions":["Use the existing document: web_sys::window().unwrap().document().unwrap() or gloo::utils::document()","If a detached document is genuinely required, use document.implementation().create_html_document(\"\")","Gate DOM access with yew::is_browser() in code shared across targets","Update copied snippets - this is a known weak spot of the old docs example"],"exampleFix":"// before\nDocument::new()\n    .expect(\"global document not set\")\n    .get_element_by_id(\"mousemoveme\")\n\n// after\ngloo::utils::document()\n    .get_element_by_id(\"mousemoveme\")","handlingStrategy":"validation","validationCode":"// Check the environment before touching DOM bindings in shared code:\nif let Some(win) = web_sys::window() {\n    let doc = win.document().expect(\"window without a document\");\n    // proceed with doc\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use gloo::utils::document() or window().document() instead of Document::new()","For detached documents, use document.implementation().create_html_document(\"\")","Gate DOM access behind yew::is_browser() in code shared across targets"],"tags":["docs","web-sys","dom","environment"],"backgroundTag":"dom-api-unavailable","analyzedSha":"0e4a05472fac4e5fce1befe60fa4a1e43a36b6a3","analyzedAt":"2026-08-22T21:16:31.212Z","schemaVersion":2},"datasetVersion":"2026-08-23T01:17:44.959Z"}