a-b-street/abstreet · error · anyhow::Error
window.location.href failed
Error message
window.location.href failed
What it means
After obtaining the window, parse_args calls window.location().href(), which returns a Result whose Err case is a JsValue. The code converts the JsValue to a String; if it is not a string (or is empty) it falls back to the literal message "window.location.href failed". This wraps a JS-side failure of the href property access into an anyhow error.
Solutions
- Log the raw JsValue in the browser console to see the underlying JS error
- Verify the page origin allows reading location.href (avoid exotic sandbox attributes)
- Consider wrapping with js_sys::Error to extract a better message than the fallback string
- Fall back to window.location.search which is less likely to fail if only the query string is needed
Example fix
// before
anyhow!(err.as_string().unwrap_or("window.location.href failed".to_string()))
// after
let msg = err.as_string().unwrap_or_else(|| format!("window.location.href failed: {:?}", err));
Err(anyhow!(msg)) Defensive patterns
Strategy: try-catch
Validate before calling
// ensure location is readable let ok = web_sys::window().map(|w| !w.location().href().is_err()).unwrap_or(false);
Try / catch
match cli_args() {
Ok(args) => use(args),
Err(e) => {
log::error!("failed to read URL args: {:?}", e);
default_args()
}
} Prevention
- Avoid exotic sandboxed iframe setups when embedding the app
- Prefer window.location.search for query strings only
- Log raw JsValue errors in the console during development
When it happens
Trigger: Calling cli_args() in a browser when reading location.href throws or returns a rejected JsValue — rare, but possible if the document origin/context is detached (e.g. window closed, about:blank in some sandboxed iframes, or the JsValue error is not a string).
Common situations: Sandboxed iframes with restricted navigation APIs; running inside a partially torn-down page; embedding the app in an environment where Location access is blocked by the host page.
Understand the failure class
Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.
Related errors
- no window?
- no window?
- window.location.set_href failed
- window.location.href failed
- unable to cast to WebGl2RenderingContext. error
AI-assisted analysis of a-b-street/abstreet@0964f29315 (2026-09-13).
Data as JSON: /api/errors/f8f9e09635a5142c.
Report an issue: GitHub.
Appendix: source
Thrown at abstutil/src/cli.rs:50
// TODO Similar to parse_args forgoing a URL decoding crate, just handle this one
// transformation
let result = args
.into_iter()
.map(|x| x.replace(" ", "%20"))
.collect::<Vec<_>>()
.join("&");
if result.is_empty() {
result
} else {
format!("?{}", result)
}
}
#[cfg(target_arch = "wasm32")]
fn parse_args() -> anyhow::Result<Vec<String>> {
let window = web_sys::window().ok_or(anyhow!("no window?"))?;
let url = window.location().href().map_err(|err| {
anyhow!(err
.as_string()
.unwrap_or("window.location.href failed".to_string()))
})?;
// Consider using a proper url parsing crate. This works fine for now, though.
let url_parts = url.split("?").collect::<Vec<_>>();
if url_parts.len() != 2 {
bail!("URL {url} doesn't seem to have query params");
}
let parts = url_parts[1]
.split("&")
.map(|x| x.replace("%20", " ").to_string())
.collect::<Vec<_>>();
Ok(parts)
}
View on GitHub (pinned to 0964f29315)