zed-industries/zed · error
Canvas returned non-finite text metrics
Error message
Canvas returned non-finite text metrics
What it means
gpui_web's `measure` calls the browser Canvas 2D `measureText` API and converts the returned TextMetrics (width, bounding box, ascent, descent) into f32 values. This error is thrown when any of those metrics is NaN or infinite, meaning the browser produced unusable measurements. The library throws it defensively because non-finite metrics would corrupt glyph layout and raster bounds downstream.
Solutions
- Validate the css_font string is a valid canvas font spec (e.g. `"16px Inter"`, not a CSS `font:` shorthand with unsupported parts) before calling measure.
- Check that the text being measured is non-empty or handle empty input before calling measure.
- Update the browser/WebView; some older or headless browsers return NaN bounding-box metrics.
- Wrap the call and fall back to approximate metrics (e.g. advance = 0 or font-size-based estimate) if the error is hit.
Example fix
// before let metrics = measure(text, "font-size: 16px; family: Inter")?; // after let metrics = measure(text, "16px Inter")?;
Defensive patterns
Strategy: validation
Validate before calling
fn is_valid_canvas_font(font: &str) -> bool {
!font.trim().is_empty() && font.contains("px") && !text.trim().is_empty()
}
if is_valid_canvas_font(css_font) {
let metrics = measure(text, css_font)?;
} Type guard
fn finite_metrics(m: &CanvasTextMetrics) -> bool {
[m.advance, m.left, m.right, m.ascent, m.descent].iter().all(|v| v.is_finite())
} Prevention
- Always pass canvas-style font strings (`16px Inter`), not CSS font shorthand.
- Never call measure with an empty text buffer; guard empty input.
- Test text measurement in the actual target browser/WebView early.
When it happens
Trigger: Calling `measure(text, css_font)` when the canvas 2D context returns non-finite TextMetrics: e.g. a malformed or empty CSS font string that the browser silently ignores leaving an undefined font state, measure_text called before a valid font is configured, or browser bugs (certain headless/embedded browsers) returning NaN for actual_bounding_box_* on empty or whitespace-only strings.
Common situations: WASM builds running in unusual browsers or embedded WebViews (e.g. headless Chromium during tests, Electron with disabled font rendering) where measureText returns NaN; passing a font string with unsupported units (e.g. `font-size: 16px` CSS shorthand instead of the canvas `16px sans-serif` form); measuring an empty string on a context whose font failed to apply.
Related errors
- Canvas text subpixel offset must be finite
- Canvas readback option could not be set
- Canvas text direction could not be set
- Canvas text font is empty
- Canvas text raster exceeds maximum dimension
AI-assisted analysis of zed-industries/zed@916fc2b8cb (2026-09-19).
Data as JSON: /api/errors/e90500f3a053eced.
Report an issue: GitHub.
Appendix: source
Thrown at crates/gpui_web/src/canvas_text.rs:101
)
})
}
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"
);
Ok(metrics)
})
}
pub(crate) fn rasterize(
text: &str,
css_font: &str,View on GitHub (pinned to 916fc2b8cb)