GraphiteEditor/Graphite · error
Failed to draw the circle
Error message
Failed to draw the circle
What it means
ctx.arc(position.x, position.y, radius, 0., TAU) maps to JS arc(), which throws IndexSizeError for a negative radius and can reject non-finite arguments. Unlike the constant-radius wrappers elsewhere in this file, radius is a caller-supplied parameter of dashed_circle, so bad geometry flows straight into the canvas API; the .expect turns the JS throw into a Rust panic.
Source
Thrown at editor/src/messages/portfolio/document/overlays/utility_types_web.rs:431
let dash_gap_width = dash_gap_width.unwrap_or(1.);
let array = js_sys::Array::new();
array.push(&JsValue::from(dash_width));
array.push(&JsValue::from(dash_gap_width));
if let Some(dash_offset) = dash_offset {
if dash_offset != 0. {
self.render_context.set_line_dash_offset(dash_offset);
}
}
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.arc(position.x, position.y, radius, 0., TAU).expect("Failed to draw the circle");
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 radius at dashed_circle entry: skip drawing unless radius.is_finite() && radius >= 0.
- Find the producer of the negative/NaN radius (zoom scale, bounds subtraction) and fix it at the source.
- Degrade .expect to a logged if-let Err so one bad circle skips instead of crashing the overlay pass.
Example fix
// before
self.render_context.arc(position.x, position.y, radius, 0., TAU).expect("Failed to draw the circle");
// after
if radius.is_finite() && radius >= 0. {
if let Err(err) = self.render_context.arc(position.x, position.y, radius, 0., TAU) {
log::warn!("Failed to draw the circle: {:?}", err);
}
} Defensive patterns
Strategy: validation
Validate before calling
fn circle_drawable(position: DVec2, radius: f64) -> bool {
position.x.is_finite() && position.y.is_finite() && radius.is_finite() && radius >= 0.
} Type guard
fn is_drawable_radius(radius: f64) -> bool {
radius.is_finite() && radius >= 0.
} Try / catch
if let Err(err) = self.render_context.arc(position.x, position.y, radius, 0., TAU) {
log::warn!("overlay circle failed: {:?}", err);
} Prevention
- Clamp any caller-computed radius to non-negative finite values before it reaches dashed_circle
- Check zoom-scale arithmetic for ways to go negative or zero
- Never .expect on web_sys canvas calls in render loops — log and skip instead
When it happens
Trigger: Any overlay caller passing a negative or NaN radius to dashed_circle — e.g., a size computed from a negative zoom scale, a half-extent of an inverted bound, or NaN propagated from document bounds.
Common situations: Handle/anchor radii scaled by zoom where the zoom math went negative or zero; layout arithmetic subtracting sizes into negative results; corrupted documents feeding non-finite bounds.
Related errors
- Failed to draw ellipse
- 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/58ff8980ff02c995.
Report an issue: GitHub.