GraphiteEditor/Graphite · error

Failed to measure the text dimensions

Error message

Failed to measure the text dimensions

What it means

The overlay text routine calls render_context.measure_text(text).expect("Failed to measure the text dimensions"); wasm-bindgen types measure_text as Result<TextMetrics, JsValue>, so any JS-level throw (invalidated/detached context, engine error) becomes a WASM panic. Per spec measureText itself does not throw for missing fonts (it returns fallback metrics), so in practice this expect fires only when the context is no longer usable.

Source

Thrown at editor/src/messages/portfolio/document/overlays/utility_types_web.rs:1057

		// └──┴──┴──┴──┘
		let pixels = [(0, 0), (2, 2)];
		for &(x, y) in &pixels {
			let index = (x + y * PATTERN_WIDTH) * 4;
			data[index..index + 4].copy_from_slice(&rgba);
		}

		let image_data = web_sys::ImageData::new_with_u8_clamped_array_and_sh(wasm_bindgen::Clamped(&data), PATTERN_WIDTH as u32, PATTERN_HEIGHT as u32).unwrap();
		pattern_context.put_image_data(&image_data, 0, 0).unwrap();
		let pattern = self.render_context.create_pattern_with_offscreen_canvas(&pattern_canvas, "repeat").unwrap().unwrap();

		self.push_path(subpaths, transform);

		self.render_context.set_fill_style_canvas_pattern(&pattern);
		self.render_context.fill();
	}

	pub fn text(&self, text: &str, font_color: &str, background_color: Option<&str>, transform: DAffine2, padding: f64, pivot: [Pivot; 2]) {
		let metrics = self.render_context.measure_text(text).expect("Failed to measure the text dimensions");
		let x = match pivot[0] {
			Pivot::Start => padding,
			Pivot::Middle => -(metrics.actual_bounding_box_right() + metrics.actual_bounding_box_left()) / 2.,
			Pivot::End => -padding - metrics.actual_bounding_box_right() + metrics.actual_bounding_box_left(),
		};
		let y = match pivot[1] {
			Pivot::Start => padding + metrics.font_bounding_box_ascent() - metrics.font_bounding_box_descent(),
			Pivot::Middle => (metrics.font_bounding_box_ascent() + metrics.font_bounding_box_descent()) / 2.,
			Pivot::End => -padding,
		};

		let [a, b, c, d, e, f] = (DAffine2::from_scale(DVec2::splat(self.viewport.scale())) * transform * DAffine2::from_translation(DVec2::new(x, y))).to_cols_array();
		self.render_context.set_transform(a, b, c, d, e, f).expect("Failed to rotate the render context to the specified angle");

		if let Some(background) = background_color {
			self.render_context.set_fill_style_str(background);
			self.render_context.fill_rect(
				-padding,

View on GitHub (pinned to c507b35645)

Solutions

  1. Stop drawing overlays for a frame when the canvas is detached or the context is lost, and rebuild the context before resuming
  2. Replace the expect with a match that logs and returns early (no label is worth aborting the editor)
  3. Keep font setup (set_font) before measure_text so engines return real metrics instead of erroring on odd state

Example fix

// before
let metrics = self.render_context.measure_text(text).expect("Failed to measure the text dimensions");

// after
let Ok(metrics) = self.render_context.measure_text(text) else {
	log::error!("Failed to measure text {text:?}");
	return;
};
Defensive patterns

Strategy: try-catch

Validate before calling

// cheap sanity check before measuring: the context must still be usable
// (wasm-bindgen exposes no isContextLost on this type; guard by owning the canvas lifetime)
assert!(self.render_context.canvas().map(|c| c.width() > 0).unwrap_or(true));

Try / catch

let metrics = match self.render_context.measure_text(text) {
	Ok(m) => m,
	Err(js_err) => {
		log::error!("measure_text failed for {text:?}: {js_err:?}");
		return;
	}
};

Prevention

When it happens

Trigger: Calling OverlayResource::text (every overlay label: angles, translation boxes, layer names) after the canvas context has been invalidated, removed, or replaced between frames.

Common situations: Canvas element removed from the DOM while overlay rendering is still scheduled; context loss during heavy GPU pressure; devtools 'discard/restore' of the tab.

Related errors


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