GraphiteEditor/Graphite · error
Failed to draw ellipse
Error message
Failed to draw ellipse
What it means
Calls ellipse_with_anticlockwise, which maps to JS CanvasRenderingContext2D.ellipse(). The browser throws IndexSizeError when radius_x or radius_y is negative, and errors can also occur with non-finite arguments; wasm-bindgen surfaces any JS throw as Err(JsValue), which this .expect escalates into a Rust panic that aborts the overlay render pass.
Source
Thrown at editor/src/messages/portfolio/document/overlays/utility_types_web.rs:368
self.render_context
.set_line_dash(&JsValue::from(array))
.map_err(|error| log::warn!("Error drawing dashed line: {:?}", error))
.ok();
}
self.render_context.begin_path();
self.render_context
.ellipse_with_anticlockwise(
center.x,
center.y,
radius_x,
radius_y,
rotation.unwrap_or_default(),
start_angle.unwrap_or_default(),
end_angle.unwrap_or(TAU),
counterclockwise.unwrap_or_default(),
)
.expect("Failed to draw ellipse");
self.render_context.set_stroke_style_str(color_stroke);
if let Some(fill_color) = color_fill {
self.render_context.set_fill_style_str(fill_color);
self.render_context.fill();
}
self.render_context.stroke();
// Reset the dash pattern back to solid
if dash_width.is_some() {
self.render_context
.set_line_dash(&JsValue::from(js_sys::Array::new()))
.map_err(|error| log::warn!("Error drawing dashed line: {:?}", error))
.ok();
}
if dash_offset.is_some() && dash_offset != Some(0.) {
self.render_context.set_line_dash_offset(0.);
}View on GitHub (pinned to c507b35645)
Solutions
- Clamp and validate radii before the call: early-return unless radius_x/radius_y are finite and >= 0.
- Trace NaN to its source — add is_finite debug assertions on viewport/document transforms when they are computed, not when they are drawn.
- Replace .expect with a logged .ok()/if-let so one bad ellipse cannot kill the whole overlay frame.
- Log the ellipse arguments when the call fails so the offending geometry is identifiable in reports.
Example fix
// before
self.render_context
.ellipse_with_anticlockwise(center.x, center.y, radius_x, radius_y, rotation, start_angle, end_angle, ccw)
.expect("Failed to draw ellipse");
// after
if radius_x.is_finite() && radius_y.is_finite() && radius_x >= 0. && radius_y >= 0. {
if let Err(err) = self.render_context.ellipse_with_anticlockwise(center.x, center.y, radius_x, radius_y, rotation, start_angle, end_angle, ccw) {
log::warn!("Failed to draw ellipse: {:?}", err);
}
} Defensive patterns
Strategy: validation
Validate before calling
fn ellipse_args_safe(center: DVec2, radius_x: f64, radius_y: f64) -> bool {
center.x.is_finite()
&& center.y.is_finite()
&& radius_x.is_finite()
&& radius_y.is_finite()
&& radius_x >= 0.
&& radius_y >= 0.
} Type guard
fn is_drawable_radius(radius: f64) -> bool {
radius.is_finite() && radius >= 0.
} Try / catch
if let Err(err) = self
.render_context
.ellipse_with_anticlockwise(center.x, center.y, radius_x, radius_y, rot, start, end, ccw)
{
log::warn!("overlay ellipse failed: {:?}", err);
} Prevention
- Clamp radii with .max(0.) wherever they are derived from bounds or zoom
- Assert transforms and bounds are finite when computed, not when drawn
- Log geometry values on draw failure so the NaN or negative source is identifiable
When it happens
Trigger: Drawing an ellipse overlay whose radii were computed from degenerate geometry — mirrored or inverted bounds where the width/height difference goes negative, or NaN leaking from a corrupted document/viewport transform — so radius_x/radius_y arrive negative or non-finite.
Common situations: Flipped/mirrored layers producing negative values in bounding-box math; division by zero zoom yielding NaN upstream; fuzzed or malformed documents feeding non-finite geometry into overlay drawing.
Related errors
- Failed to draw the circle
- Failed to draw hover ring
- Failed to draw main ring
- Failed to transform circle
- transform should be able to be set to be able to account for
AI-assisted analysis of GraphiteEditor/Graphite@c507b35645 (2026-08-16).
Data as JSON: /api/errors/bea77a217980df88.
Report an issue: GitHub.