zed-industries/zed · error

measuring Canvas text

Error message

measuring Canvas text: {error:?}

What it means

Thrown in measure() when canvas.context.measure_text(text) returns a rejected JS promise or throws, after configure(css_font) succeeded. It means the browser refused to compute text metrics for the given text/font on the shared OffscreenCanvas — usually a browser-internal error from the 2D context (empty or invalid font state, oversized string, or a context that has been invalidated), not a problem with the caller's text.

Solutions

  1. Retry the measurement once with a freshly created OffscreenCanvas, as the 2D context may have become invalid
  2. Fall back to approximating metrics from a default font (e.g. cache last-good advance/ascent/descent for the font) so layout can proceed
  3. Log the JsValue error via js_sys::Error::from to surface the browser's message before deciding on retry vs fallback
  4. Sanity-check css_font against known-good values before calling, since a silently ignored bad font leaves the context in a reset ('10px sans-serif') state
Defensive patterns

Strategy: retry

When it happens

Trigger: Thrown at crates/gpui_web/src/canvas_text.rs:93 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of zed-industries/zed@916fc2b8cb (2026-09-19). Data as JSON: /api/errors/7a77318f49effcb9. Report an issue: GitHub.

Appendix: source

Thrown at crates/gpui_web/src/canvas_text.rs:93

            .context("Canvas text renderer was called reentrantly")?;
        if canvas.is_none() {
            *canvas = Some(TextCanvas::new()?);
        }
        operation(
            canvas
                .as_mut()
                .context("Canvas text renderer is unavailable")?,
        )
    })
}

pub(crate) fn measure(text: &str, css_font: &str) -> Result<CanvasTextMetrics> {
    with_canvas(|canvas| {
        canvas.configure(css_font)?;
        let metrics = canvas
            .context
            .measure_text(text)
            .map_err(|error| anyhow!("measuring Canvas text: {error:?}"))?;
        let metrics = CanvasTextMetrics {
            advance: metrics.width() as f32,
            left: -metrics.actual_bounding_box_left() as f32,
            right: metrics.actual_bounding_box_right() as f32,
            ascent: metrics.actual_bounding_box_ascent() as f32,
            descent: metrics.actual_bounding_box_descent() as f32,
        };
        ensure!(
            [
                metrics.advance,
                metrics.left,
                metrics.right,
                metrics.ascent,
                metrics.descent
            ]
            .into_iter()
            .all(f32::is_finite),
            "Canvas returned non-finite text metrics"

View on GitHub (pinned to 916fc2b8cb)