{"record":{"id":"cb761ac70affbc2a","repo":"a-b-street/abstreet","slug":"window-location-href-failed-url","errorCode":null,"errorMessage":"window.location.href failed","messagePattern":"window\\.location\\.href failed","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"warning","filePath":"widgetry/src/tools/url.rs","lineNumber":110,"sourceCode":"        let cam_zoom = 1.0 / horiz_meters_per_pixel;\n\n        Some((pt, cam_zoom))\n    }\n}\n\nfn must_update_url(transform: Box<dyn Fn(String) -> String>) {\n    if let Err(err) = update_url(transform) {\n        warn!(\"Couldn't update URL: {}\", err);\n    }\n}\n\n#[allow(unused_variables)]\nfn update_url(transform: Box<dyn Fn(String) -> String>) -> Result<()> {\n    #[cfg(target_arch = \"wasm32\")]\n    {\n        let window = web_sys::window().ok_or(anyhow!(\"no window?\"))?;\n        let url = window.location().href().map_err(|err| {\n            anyhow!(err\n                .as_string()\n                .unwrap_or(\"window.location.href failed\".to_string()))\n        })?;\n        let new_url = (transform)(url);\n\n        // Setting window.location.href may seem like the obvious thing to do, but that actually\n        // refreshes the page. This method just changes the URL and doesn't mess up history. See\n        // https://developer.mozilla.org/en-US/docs/Web/API/History_API/Working_with_the_History_API.\n        let history = window.history().map_err(|err| {\n            anyhow!(err\n                .as_string()\n                .unwrap_or(\"window.history failed\".to_string()))\n        })?;\n        history\n            .replace_state_with_url(&wasm_bindgen::JsValue::NULL, \"\", Some(&new_url))\n            .map_err(|err| {\n                anyhow!(err\n                    .as_string()","sourceCodeStart":92,"sourceCodeEnd":128,"githubUrl":"https://github.com/a-b-street/abstreet/blob/0964f29315820c91b171b585eb51e300164e9197/widgetry/src/tools/url.rs#L92-L128","documentation":"After getting the window, update_url calls window.location().href() to read the current URL. This returns a Result in web-sys; on a JS exception it throws this error, falling back to 'window.location.href failed' when the JsValue error has no string form.","triggerScenarios":"Reading location.href throws in the browser: unusual security contexts (sandboxed iframe denying navigation/Location access), opaque origins (e.g. sandboxed about:srcdoc frames), or exotic embedded browsers.","commonSituations":"App embedded in a sandboxed iframe without allow-same-origin, running from a data:/blob: origin, privacy-hardened browsers restricting location access.","solutions":["Embed the app in a non-sandboxed iframe or add allow-same-origin to the sandbox attribute","Serve the page over http(s) from a real origin rather than file:/data:/blob:","Check the browser console for the underlying SecurityError","Fall back to skipping URL persistence when the origin is opaque"],"exampleFix":"// sandboxed iframe causing SecurityError\n// before\n<iframe sandbox=\"allow-scripts\" src=\"app.html\"></iframe>\n// after\n<iframe sandbox=\"allow-scripts allow-same-origin\" src=\"app.html\"></iframe>","handlingStrategy":"try-catch","validationCode":"// opaque-origin check\nlet origin_ok = window.location().origin().map(|o| !o.is_empty() && o != \"null\").unwrap_or(false);\nif !origin_ok { skip_url_update(); }","typeGuard":null,"tryCatchPattern":"let url = window.location().href().map_err(|e| anyhow!(e.as_string().unwrap_or_else(|| \"window.location.href failed\".into())));\nif url.is_err() { log::warn!(\"cannot read location; skipping URL update\"); return Ok(()); }","preventionTips":["Serve the app over http(s) with a real origin; avoid data:/blob:/file: origins","If embedding in an iframe, include allow-same-origin in the sandbox attribute","Test in target browsers/embedded webviews early","Degrade gracefully: treat URL persistence as best-effort"],"tags":["wasm","browser","url","web-sys"],"backgroundTag":"invalid-url","analyzedSha":"0964f29315820c91b171b585eb51e300164e9197","analyzedAt":"2026-09-13T18:02:03.421Z","contentChangedAt":"2026-09-13T18:02:03.421Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}