{"record":{"id":"a7646d121e6cfb5c","repo":"linera-io/linera-protocol","slug":"we-need-to-run-in-a-document-context","errorCode":null,"errorMessage":"we need to run in a document context","messagePattern":"we need to run in a document context","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"web/@linera/client/src/lock.rs","lineNumber":106,"sourceCode":"                            })\n                        } else {\n                            release.call0(&JsValue::NULL).unwrap_throw();\n                            None\n                        };\n\n                        resolve\n                            .call1(\n                                &JsValue::NULL,\n                                &serde_wasm_bindgen::to_value(&value).unwrap_throw(),\n                            )\n                            .unwrap_throw();\n\n                        std::mem::forget(value);\n                    })\n                });\n\n            let _: js_sys::Promise = web_sys::window()\n                .expect(\"we need to run in a document context\")\n                .navigator()\n                .locks()\n                .request_with_options_and_callback(\n                    name,\n                    &options,\n                    callback.as_ref().unchecked_ref(),\n                );\n\n            callback.forget();\n        }))\n        .await\n        .unwrap_throw();\n\n        serde_wasm_bindgen::from_value::<Option<Self>>(value)\n            .unwrap_throw()\n            .ok_or_else(|| Error::Contended { name: name.into() })\n    }\n}","sourceCodeStart":88,"sourceCodeEnd":124,"githubUrl":"https://github.com/linera-io/linera-protocol/blob/6c226ddcb332ef55118dc8d0aafbd093d5420899/web/@linera/client/src/lock.rs#L88-L124","documentation":"The @linera/client wallet lock is built on the browser Web Locks API, reached through `web_sys::window()`. window() returns Option and is None outside a window/document context: Web Workers (their global object is not `window`), Node.js and other non-browser WASM runtimes, SSR, and DOM-less test runners. `.expect(\"we need to run in a document context\")` panics as soon as try_acquire is called in such a context, before any lock request is made.","triggerScenarios":"Calling Lock::try_acquire from code running in a Web Worker; executing the client WASM under Node (e.g. wasm-bindgen-test with the nodejs target); SSR/prerendering that imports and runs the wallet module; unit tests under jsdom where window exists but navigator.locks is missing.","commonSituations":"Moving wallet logic into a worker for background signing; CI unit tests running under node instead of a headless browser; older browsers without navigator.locks (pre-Chrome 69 / Firefox 96 / Safari 15.4) failing the follow-up calls; SSR frameworks pulling in the browser client bundle.","solutions":["Run the locking code on the main browser thread / a real browser environment (a document context)","Guard the call: check web_sys::window().is_some() (and that navigator.locks exists) and skip or use a fallback when absent","In tests, run wasm-bindgen-test with a browser target (chrome) instead of node","If Web Locks is unavailable, fall back to a storage/BroadcastChannel-based mutual exclusion for the wallet"],"exampleFix":"// before\nlet lock = Lock::try_acquire(\"wallet\").await?; // panics in workers/node: no `window`\n\n// after\nlet lock = if web_locks_available() {\n    Some(Lock::try_acquire(\"wallet\").await?)\n} else {\n    None // degrade gracefully outside a document context\n};","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"fn web_locks_available() -> bool {\n    web_sys::window().is_some_and(|w| {\n        js_sys::Reflect::has(&w.navigator(), &wasm_bindgen::JsValue::from_str(\"locks\"))\n            .unwrap_or(false)\n    })\n}","tryCatchPattern":null,"preventionTips":["Feature-detect window + navigator.locks before any Web Locks call","Keep wallet-locking code on the main thread; pass results to workers instead","Run wasm-bindgen tests with a browser target (chrome) so document APIs exist"],"tags":["wasm","browser","web-locks","web-sys","wasm-bindgen"],"backgroundTag":"browser-api-unavailable","analyzedSha":"6c226ddcb332ef55118dc8d0aafbd093d5420899","analyzedAt":"2026-08-22T22:49:09.787Z","schemaVersion":2},"datasetVersion":"2026-08-23T01:17:44.959Z"}