GraphiteEditor/Graphite · warning
transform should be able to be reset to be able to account f
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.
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)
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 for
- Failed to get canvas context
- Failed to get canvas context
- Failed to draw ellipse
- Failed to transform circle
AI-assisted analysis of GraphiteEditor/Graphite@c507b35645 (2026-08-16).
Data as JSON: /api/errors/36391a8f5373667f.
Report an issue: GitHub.