GraphiteEditor/Graphite · error

Failed to get canvas context

Error message

Failed to get canvas context

What it means

WASM-only helper overlay_canvas_context(): it locates the overlays canvas via overlay_canvas_element() (which returns None when window, document, or the [data-overlays-canvas] element is missing) and then demands a 2D context. The ? chain covers the element being absent, but .expect("Failed to get canvas context") panics when the element exists yet get_context("2d") yields null or the returned object fails dyn_into::<CanvasRenderingContext2d>() — the same one-context-per-canvas browser rule as the message-handler path.

Source

Thrown at editor/src/messages/portfolio/document/overlays/utility_functions.rs:30

use std::collections::HashMap;
#[cfg(target_family = "wasm")]
use wasm_bindgen::JsCast;

#[cfg(target_family = "wasm")]
pub fn overlay_canvas_element() -> Option<web_sys::HtmlCanvasElement> {
	let window = web_sys::window()?;
	let document = window.document()?;
	let canvas = document.query_selector("[data-overlays-canvas]").ok().flatten()?;
	canvas.dyn_into::<web_sys::HtmlCanvasElement>().ok()
}

#[cfg(target_family = "wasm")]
pub fn overlay_canvas_context() -> web_sys::CanvasRenderingContext2d {
	let create_context = || {
		let context = overlay_canvas_element()?.get_context("2d").ok().flatten()?;
		context.dyn_into().ok()
	};
	create_context().expect("Failed to get canvas context")
}

pub fn selected_segments(network_interface: &NodeNetworkInterface, shape_editor: &ShapeState) -> HashMap<LayerNodeIdentifier, Vec<SegmentId>> {
	let mut map = HashMap::new();

	for (layer, state) in &shape_editor.selected_shape_state {
		let Some(vector) = network_interface.compute_modified_vector(*layer) else { continue };
		let selected_segments = selected_segments_for_layer(&vector, state);

		map.insert(*layer, selected_segments);
	}

	map
}

pub fn selected_segments_for_layer(vector: &Vector, state: &SelectedLayerState) -> Vec<SegmentId> {
	let selected_anchors = state
		.selected_points()

View on GitHub (pinned to c507b35645)

Solutions

  1. Make overlay_canvas_context return Option<CanvasRenderingContext2d> and let callers skip overlay drawing on None.
  2. Ensure nothing else requests a non-2D context from the [data-overlays-canvas] element.
  3. Log a warning instead of panicking so the overlay layer degrades without crashing the app.
  4. Re-query the canvas element when the context lookup fails, in case the DOM node was replaced.

Example fix

// before
create_context().expect("Failed to get canvas context")

// after
pub fn overlay_canvas_context() -> Option<web_sys::CanvasRenderingContext2d> {
	let context = overlay_canvas_element()?.get_context("2d").ok().flatten()?;
	context.dyn_into().ok()
}
// callers: let Some(ctx) = overlay_canvas_context() else { return; };
Defensive patterns

Strategy: validation

Validate before calling

// make absence explicit and checkable
fn try_overlay_canvas_context() -> Option<web_sys::CanvasRenderingContext2d> {
	let context = overlay_canvas_element()?.get_context("2d").ok().flatten()?;
	context.dyn_into().ok()
}
// caller: if try_overlay_canvas_context().is_none() { skip overlay drawing }

Type guard

fn overlay_context_available() -> bool {
	web_sys::window().is_some()
		&& overlay_canvas_element()
			.and_then(|c| c.get_context("2d").ok().flatten())
			.is_some()
}

Try / catch

match create_context() {
	Some(ctx) => ctx,
	None => {
		log::warn!("Overlay canvas 2D context unavailable");
		return;
	}
}

Prevention

When it happens

Trigger: Overlay drawing utilities invoked while the overlays canvas element exists but its context was already claimed as webgl/webgpu, or 2D context creation fails; also when a non-2D context object comes back so dyn_into errors.

Common situations: Embedders or integrations reusing the overlay canvas for WebGL; headless/test environments where canvas contexts are unavailable; DOM changes removing or duplicating the overlays canvas element.

Related errors


AI-assisted analysis of GraphiteEditor/Graphite@c507b35645 (2026-08-16). Data as JSON: /api/errors/7d72bf4d021704f5. Report an issue: GitHub.