a-b-street/abstreet · error · anyhow::Error
no window?
Error message
no window?
What it means
In the wasm32 build of abstutil's CLI argument parsing, parse_args first needs the browser's global Window object via web_sys::window(). If that returns None there is no JS global scope to read the URL query string from, so the function aborts with anyhow!("no window?"). This guards code that must only ever run inside a browser.
Solutions
- Ensure the code runs in a real browser main thread where window exists
- For non-browser wasm environments, add a JS shim that defines a global window object before the module loads
- Restructure to pass CLI args explicitly instead of reading window.location.href
- Use #[cfg] to gate browser-only code paths and provide a non-wasm fallback
Example fix
// before
let window = web_sys::window().ok_or(anyhow!("no window?"))?;
// after
let Some(window) = web_sys::window() else {
return Ok(std::env::args().skip(1).collect()); // non-browser fallback
}; Defensive patterns
Strategy: fallback
Validate before calling
// before calling wasm-only arg parsing
if web_sys::window().is_none() {
// non-browser environment: skip or use env::args
} Type guard
fn has_window() -> bool { web_sys::window().is_some() } Try / catch
match cli_args() {
Ok(args) => use(args),
Err(e) if e.to_string().contains("no window?") => fallback_args(),
Err(e) => report(e),
} Prevention
- Only run wasm code paths that touch web-sys inside a browser main thread
- Add an early environment check before any window-dependent API
- Provide non-browser fallbacks for arg/URL parsing
When it happens
Trigger: Calling cli_args() (wasm32 target) from a WebAssembly context that is not a browser main thread with a DOM window — e.g. running in Node/wasmtime, a web worker without window shim, or before JS glue sets up globals.
Common situations: Testing wasm code headlessly in Node; running wasm tests outside a browser; embedding the wasm module in a worker; calling parse_args during non-DOM initialization.
Understand the failure class
Background: "unsupported platform" / "not supported on this platform" errors: what they mean and how to fix them — this error's family across 47 libraries.
Related errors
- window.location.href failed
- no window?
- window.location.set_href failed
- unable to cast to WebGl2RenderingContext. error
- no window?
AI-assisted analysis of a-b-street/abstreet@0964f29315 (2026-09-13).
Data as JSON: /api/errors/6c9c10622b5417b8.
Report an issue: GitHub.
Appendix: source
Thrown at abstutil/src/cli.rs:48
/// between arguments. The string returned starts with `?`, unless the arguments are all empty.
pub fn args_to_query_string(args: Vec<String>) -> String {
// 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)