a-b-street/abstreet · error · anyhow::Error

no window?

Error message

no window?

What it means

read_local_storage on wasm requires a browser window; web_sys::window() returning None means the code is executing outside a browser document context. The library maps that None to the "no window?" error instead of panicking. It happens before localStorage is even touched.

Solutions

  1. Only call localStorage-backed APIs from the main browser thread/document context
  2. Route reads through a message channel to the main thread when in a worker
  3. In tests, stub web_sys::window or feature-gate the storage path
  4. Check web_sys::window().is_some() in your own code before invoking the API

Example fix

// before
let data = abstio::slurp_file(path); // panics/errors in worker
// after
let data = if web_sys::window().is_some() {
    abstio::slurp_file(path)
} else {
    // worker fallback: fetch from network or postMessage to main thread
};
Defensive patterns

Strategy: type-guard

Validate before calling

let in_browser = web_sys::window().is_some();

Type guard

fn has_window() -> bool { web_sys::window().is_some() }

Try / catch

let raw = if has_window() {
    slurp_file(path).unwrap_or_default()
} else {
    // worker/native fallback
    fetch_or_default(path)
};

Prevention

When it happens

Trigger: Calling abstio::slurp_file or maybe_read_binary (which call read_local_storage) from a wasm build running in a non-browser context: a worker without a window, a Node/wasm-time test harness, or code executing before the document exists.

Common situations: Unit tests of wasm-targeted code run natively or in headless runtimes without a DOM; service workers / web workers where window is undefined; calling storage APIs during early startup before the page context is ready.

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


AI-assisted analysis of a-b-street/abstreet@0964f29315 (2026-09-13). Data as JSON: /api/errors/f929761b3db0cb3b. Report an issue: GitHub.

Appendix: source

Thrown at abstio/src/io_web.rs:166

            encoded.len()
        )))
    })?;
    Ok(())
}

pub fn delete_file<I: AsRef<str>>(path: I) {
    let path = path.as_ref();
    if !path.starts_with(&path_player("")) {
        warn!("Not deleting {}", path);
        return;
    }
    let window = web_sys::window().unwrap();
    let storage = window.local_storage().unwrap().unwrap();
    storage.remove_item(path).unwrap();
}

fn read_local_storage(path: &str) -> Result<String> {
    let window = web_sys::window().ok_or(anyhow!("no window?"))?;
    let storage = window
        .local_storage()
        .map_err(|err| {
            anyhow!(err
                .as_string()
                .unwrap_or("local_storage failed".to_string()))
        })?
        .ok_or(anyhow!("no local_storage?"))?;
    let string = storage
        .get_item(&path)
        .map_err(|err| anyhow!(err.as_string().unwrap_or("get_item failed".to_string())))?
        .ok_or(anyhow!("{} missing from local storage", path))?;
    Ok(string)
}

fn list_local_storage_keys() -> Vec<String> {
    let window = web_sys::window().unwrap();
    let storage = window.local_storage().unwrap().unwrap();

View on GitHub (pinned to 0964f29315)