GraphiteEditor/Graphite · warning
transform should be able to be reset to be able to account…
Error message
transform should be able to be reset to be able to account for DPI
What it means
end_dpi_aware_transform calls ctx.reset_transform(). Per the HTML spec resetTransform() is equivalent to setTransform(1, 0, 0, 1, 0, 0), and the identity matrix is always invertible, so on a live 2D context this call effectively cannot throw; web_sys still types it as Result and the .expect is purely defensive. If it ever fires it indicates an invalid or lost context rather than a geometry bug.
Solutions
- Treat it as defensive: if observed, check canvas/context health and look for an earlier root-cause panic (e.g., a set_transform NaN failure in the same frame).
- Degrade to a logged .ok() so a context anomaly cannot abort the overlay pass.
- Ensure the context cache is invalidated when the underlying canvas element is recreated.
Example fix
// before
self.render_context.reset_transform().expect("transform should be able to be reset to be able to account for DPI");
// after — resetTransform() applies the identity matrix and cannot fail on a live context
if let Err(err) = self.render_context.reset_transform() {
log::warn!("Failed to reset canvas transform: {:?}", err);
} Defensive patterns
Strategy: fallback
Try / catch
if let Err(err) = self.render_context.reset_transform() {
log::warn!("failed to reset canvas transform (context may be invalid): {:?}", err);
} Prevention
- Treat a resetTransform failure as a signal the context is invalid — re-query the canvas rather than reusing the cached context
- Invalidate context caches when the canvas element is recreated
- Keep reset/set transform pairs balanced so stale transforms never accumulate
When it happens
Trigger: Practically unreachable on a valid context. Conceivable only with an already-invalid context (lost after a GPU reset or detached canvas) or an engine-level failure inside resetTransform.
Common situations: Appearing in crash reports almost always as a secondary effect of a corrupted render context or a stale cached context after the canvas element was replaced — not as an independent defect.
Related errors
- transform should be able to be set to be able to account…
- Failed to draw ellipse
- Failed to draw hover ring
- Failed to draw main ring
- Failed to draw the circle
AI-assisted analysis of GraphiteEditor/Graphite@c507b35645 (2026-08-16).
Data as JSON: /api/errors/36391a8f5373667f.
Report an issue: GitHub.
Appendix: source
Thrown at editor/src/messages/portfolio/document/overlays/utility_types_web.rs:620
self.draw_triangle(mid + edge * (3. + SKEW_TRIANGLE_OFFSET), edge, SKEW_TRIANGLE_SIZE, None, None);
}
}
/// Transforms the canvas context to adjust for DPI scaling
///
/// Overwrites all existing tranforms. This operation can be reversed with [`Self::reset_transform`].
fn start_dpi_aware_transform(&self) {
let [a, b, c, d, e, f] = DAffine2::from_scale(DVec2::splat(self.viewport.scale())).to_cols_array();
self.render_context
.set_transform(a, b, c, d, e, f)
.expect("transform should be able to be set to be able to account for DPI");
}
/// Un-transforms the Canvas context to adjust for DPI scaling
///
/// Warning: this function doesn't only reset the DPI scaling adjustment, it resets the entire transform.
fn end_dpi_aware_transform(&self) {
self.render_context.reset_transform().expect("transform should be able to be reset to be able to account for DPI");
}
pub fn square(&mut self, position: DVec2, size: Option<f64>, color_fill: Option<&str>, color_stroke: Option<&str>) {
let size = size.unwrap_or(MANIPULATOR_GROUP_MARKER_SIZE);
let color_fill = color_fill.unwrap_or(COLOR_OVERLAY_WHITE);
let color_stroke = color_stroke.unwrap_or(COLOR_OVERLAY_BLUE);
let position = self.snap_to_physical_pixel_center(position);
let corner = position - DVec2::splat(size) / 2.;
self.start_dpi_aware_transform();
self.render_context.begin_path();
self.render_context.rect(corner.x, corner.y, size, size);
self.render_context.set_fill_style_str(color_fill);
self.render_context.set_stroke_style_str(color_stroke);
self.render_context.set_line_width(1.);
self.render_context.fill();View on GitHub (pinned to c507b35645)