a-b-street/abstreet · error · anyhow::Error
unable to cast to WebGl2RenderingContext. error
Error message
unable to cast to WebGl2RenderingContext. error: {:?} What it means
After obtaining the WebGL 2 context object, it must be cast via dyn_into::<WebGl2RenderingContext>. If the returned JsValue is not actually a WebGl2RenderingContext (unexpected object type from the bindings), the cast fails and this error is raised. This is a wasm-bindgen type mismatch, rare in practice.
Solutions
- Update and align web-sys and wasm-bindgen versions (cargo update) and rebuild the wasm target.
- Clear stale build artifacts (cargo clean, rm -rf target) to regenerate bindings.
- Test in a standard browser to rule out getContext shims or extension interference.
- Log the failing JsValue to identify what object was actually returned.
Example fix
// before
.dyn_into::<web_sys::WebGl2RenderingContext>()
.map_err(|err| anyhow!("unable to cast to WebGl2RenderingContext. error: {:?}", err))?;
// after: dependency alignment
// Cargo.toml: keep web-sys and wasm-bindgen on matching, current versions
// then: cargo clean && cargo build --target wasm32-unknown-unknown Defensive patterns
Strategy: retry
Try / catch
// Retry once after a clean rebuild on cast failure
match webgl2_glow_context(canvas) {
Err(e) if e.to_string().contains("unable to cast") => {
// usually stale bindings: advise cargo clean + aligned deps, then retry
Err(anyhow!("stale wasm bindings? run: cargo clean && cargo build --target wasm32-unknown-unknown"))
}
other => other,
} Prevention
- Keep web-sys and wasm-bindgen versions aligned and current
- Rebuild the wasm target after dependency upgrades (clear caches)
- Avoid getContext shims or wrappers around the canvas
- Test rendering setup across major browsers in CI
When it happens
Trigger: canvas.get_context("webgl2") returns a JsValue that fails dyn_into::<web_sys::WebGl2RenderingContext>() — e.g., a mismatched web-sys version, a context acquired as a different interface, or unusual browser/proxy behavior.
Common situations: Version mismatch between web-sys/wasm-bindgen crates and generated bindings; running in environments that shim getContext with non-standard objects; build caches with stale bindings after upgrading dependencies.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- no window?
- window.location.href failed
- no window?
- error getting context for WebGL 2.0
- Browser doesn't support WebGL 2.0
AI-assisted analysis of a-b-street/abstreet@0964f29315 (2026-09-13).
Data as JSON: /api/errors/40606ccd8cffe17a.
Report an issue: GitHub.
Appendix: source
Thrown at widgetry/src/backend_glow_wasm.rs:90
"failed to build WebGL 2.0 context with error: \"{}\". Trying WebGL 1.0 instead...",
err
);
webgl1_glow_context(&canvas).and_then(|gl| {
is_gl2 = false;
webgl1_program(gl)
})
})
.unwrap();
fn webgl2_glow_context(canvas: &web_sys::HtmlCanvasElement) -> Result<glow::Context> {
let maybe_context: Option<_> = canvas
.get_context("webgl2")
.map_err(|err| anyhow!("error getting context for WebGL 2.0: {:?}", err))?;
let js_webgl2_context =
maybe_context.ok_or(anyhow!("Browser doesn't support WebGL 2.0"))?;
let webgl2_context = js_webgl2_context
.dyn_into::<web_sys::WebGl2RenderingContext>()
.map_err(|err| anyhow!("unable to cast to WebGl2RenderingContext. error: {:?}", err))?;
Ok(glow::Context::from_webgl2_context(webgl2_context))
}
fn webgl1_glow_context(canvas: &web_sys::HtmlCanvasElement) -> Result<glow::Context> {
let maybe_context: Option<_> = canvas
.get_context("webgl")
.map_err(|err| anyhow!("error getting context for WebGL 1.0: {:?}", err))?;
let js_webgl1_context =
maybe_context.ok_or(anyhow!("Browser doesn't support WebGL 1.0"))?;
let webgl1_context = js_webgl1_context
.dyn_into::<web_sys::WebGlRenderingContext>()
.map_err(|err| anyhow!("unable to cast to WebGlRenderingContext. error: {:?}", err))?;
Ok(glow::Context::from_webgl1_context(webgl1_context))
}
(
PrerenderInnards::new(gl, is_gl2, program, Some(WindowAdapter(winit_window))),
event_loop,View on GitHub (pinned to 0964f29315)