dotnet/wpf · error · InvalidOperationException
SR.GeneralTransform_TransformFailed
Error message
SR.GeneralTransform_TransformFailed
What it means
GeneralTransform.Transform(Point) throws InvalidOperationException wrapping SR.GeneralTransform_TransformFailed when TryTransform returns false, i.e., the transform could not map the point (typically because the visual is not connected to a presentation source or the transform is degenerate/non-invertible). Unlike TryTransform, Transform treats failure as an exception rather than returning false.
Solutions
- Prefer TryTransform and handle the false return instead of letting Transform throw.
- Defer the transform until the visual is loaded (handle the Loaded event or check IsLoaded) so coordinates are valid.
- Verify the transform matrix is invertible (no zero scale) before transforming.
- Use PointToScreen/PointFromScreen alternatives if the visual is disconnected from the presentation source.
Example fix
// before
var pt = generalTransform.Transform(anchorPoint);
// after
if (generalTransform.TryTransform(anchorPoint, out var pt))
{
// use pt
}
else
{
pt = anchorPoint; // fallback
} Defensive patterns
Strategy: try-catch
Validate before calling
bool canTransform = visual.IsLoaded && generalTransform != null && !generalTransform.Value.HasInverse == false; // prefer TryTransform
if (!generalTransform.TryTransform(point, out _)) { /* skip or defer */ } Type guard
bool IsTransformable(Visual v) => v != null && v.IsLoaded;
Try / catch
try
{
transformed = generalTransform.Transform(point);
}
catch (InvalidOperationException)
{
// visual not ready or singular transform
transformed = point; // or defer until Loaded
} Prevention
- Run coordinate transformations only after the element is loaded and measured (Loaded event).
- Prefer TryTransform over Transform when failure is an expected, recoverable condition.
- Check transform matrices for zero-scale/degenerate values before mapping points.
- For popup/context-menu placement, recompute offsets in the PlacementTarget's Loaded handler rather than in the constructor.
When it happens
Trigger: Calling Transform, TransformToAncestor, or TransformToDescendant on a Visual whose transform matrix is singular (zero scale) or whose coordinates cannot be computed because the visual has no valid layout/presentation source yet.
Common situations: Hit-testing or positioning popups/context menus before the element is loaded and rendered (IsLoaded == false); transforms involving a ScaleTransform with scale 0; adorner coordinate math (pointOnSelectionAdorner, pointOnInnerCanvas) running too early in the visual tree lifecycle.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- SR.BitmapCacheBrush_RelativeTransformChanged
- Animation_Invalid_DefaultValue
- Cannot remove signature from read-only file.
- Image_EncoderNoColorContext
- Image_EncoderNoGlobalMetadata
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/18e3553a6a77b784.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/GeneralTransform.cs:46
/// <summary>
/// Transform a point
///
/// If the transformation does not succeed, this will throw an InvalidOperationException.
/// If you don't want to try/catch, call TryTransform instead and check the boolean it
/// returns.
///
/// Note that this method will always succeed when called on a subclass of Transform
/// </summary>
/// <param name="point">Input point</param>
/// <returns>The transformed point</returns>
public Point Transform(Point point)
{
Point transformedPoint;
if (!TryTransform(point, out transformedPoint))
{
throw new InvalidOperationException(SR.Format(SR.GeneralTransform_TransformFailed, null));
}
return transformedPoint;
}
/// <summary>
/// Transforms the bounding box to the smallest axis aligned bounding box
/// that contains all the points in the original bounding box
/// </summary>
/// <param name="rect">Bounding box</param>
/// <returns>The transformed bounding box</returns>
public abstract Rect TransformBounds(Rect rect);
/// <summary>
/// Returns the inverse transform if it has an inverse, null otherwise
/// </summary>
public abstract GeneralTransform Inverse { get; }View on GitHub (pinned to 81131a70a4)