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

window.location.set_href failed

Error message

window.location.set_href failed

What it means

set_href calls window.location().set_href(url), which returns a Result<JsValue> that resolves after the browser attempts navigation; failure is a JsValue converted with as_string(), falling back to "window.location.set_href failed" if the error isn't a string. This means the browser refused the navigation request.

Solutions

  1. Verify the URL is absolute and well-formed (include https:// scheme)
  2. Ensure the iframe sandbox permits top navigation (allow-top-navigation) or open in a new tab with window.open instead
  3. Check browser console for the underlying JS error
  4. Avoid building URLs with unencoded special characters

Example fix

// before
set_href("abst://myapp")?;
// after
set_href("https://abstreet.org/myapp.html")?;
Defensive patterns

Strategy: try-catch

Validate before calling

// validate the URL before navigation
new URL(url); // throws in JS if malformed
if (!url.startsWith('http')) throw new Error('set_href needs an absolute URL');

Try / catch

match set_href(url) {
    Ok(_) => {},
    Err(e) => log::error!("set_href failed: {:?}", e), // inspect browser console too
}

Prevention

When it happens

Trigger: Calling set_href with a URL the browser blocks: invalid URL format, cross-origin navigation blocked in sandboxed iframes, or a popup/iframe sandbox without allow-top-navigation.

Common situations: App embedded in a sandboxed iframe attempting top-level navigation; malformed hand-built URL (missing scheme); browser extension or CSP blocking navigation.

Understand the failure class

Background: "Invalid URL" / "URL cannot be empty": fix the malformed or missing URL behind request-construction failures — this error's family across 50 libraries.

Related errors


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

Appendix: source

Thrown at map_gui/src/tools/title_screen.rs:243

                Transition::Push(PopupMsg::new_state(ctx, "Error", vec![err.to_string()]))
            }

            // On Windows, all we can do is open a new child process. Not sure how to end the
            // current or detach.
            #[cfg(windows)]
            {
                abstutil::must_run_cmd(Command::new(binary).args(args));
                Transition::Keep
            }
        }

        // On web, leave the current page and go to another.
        #[cfg(target_arch = "wasm32")]
        {
            fn set_href(url: &str) -> anyhow::Result<()> {
                let window = web_sys::window().ok_or(anyhow!("no window?"))?;
                window.location().set_href(url).map_err(|err| {
                    anyhow!(err
                        .as_string()
                        .unwrap_or("window.location.set_href failed".to_string()))
                })
            }

            let page = match self {
                Executable::ABStreet => "abstreet",
                Executable::FifteenMin => "fifteen_min",
                Executable::OSMViewer => "osm_viewer",
                // This only works on native
                Executable::ParkingMapper => unreachable!(),
                Executable::Santa => "santa",
                Executable::RawMapEditor => "map_editor",
                Executable::LTN => "ltn",
            };
            let url = format!("{}.html{}", page, abstutil::args_to_query_string(args));
            if let Err(err) = set_href(&url) {
                return Transition::Push(PopupMsg::new_state(

View on GitHub (pinned to 0964f29315)