dotnet/wpf · error · ArgumentException
SR.MatrixNotInvertible
Error message
SR.MatrixNotInvertible
What it means
StrokeCollection.Transform requires an invertible Matrix because applying a non-invertible (singular/degenerate) transform to strokes would irreversibly collapse stroke geometry. When transformMatrix.HasInverse is false the method throws ArgumentException with SR.MatrixNotInvertible. This mirrors the general WPF convention that geometry transforms must be invertible.
Solutions
- Check matrix.HasInverse before calling Transform and substitute an identity or corrected matrix when it is false.
- Fix the source of the zero scale factor (clamp scaleX/scaleY to non-zero minimums in your sizing code).
- Catch ArgumentException around Transform and apply a fallback transform if degenerate input is possible.
Example fix
// before
strokes.Transform(matrix, true); // matrix has scale (0, 1)
// after
if (matrix.HasInverse)
strokes.Transform(matrix, true);
else
strokes.Transform(Matrix.Identity, true); Defensive patterns
Strategy: validation
Validate before calling
if (!transformMatrix.HasInverse)
transformMatrix = Matrix.Identity; // or fix scale factors
strokes.Transform(transformMatrix, applyToStylusTip); Type guard
static bool IsApplicable(Matrix m) => m.HasInverse;
Try / catch
try { strokes.Transform(matrix, true); }
catch (ArgumentException ex) when (ex.Message.Contains("invert")) { strokes.Transform(Matrix.Identity, true); } Prevention
- Clamp computed scale factors to a non-zero minimum before building the Matrix.
- Check HasInverse on any dynamically composed Matrix before use.
- Avoid hand-building matrices with zero scale entries from user input.
When it happens
Trigger: Calling StrokeCollection.Transform(matrix, applyToStylusTip) where matrix is singular — e.g. a scale of 0 on either axis, a matrix built from Scale(0,0), or a hand-built matrix whose determinant is zero.
Common situations: Dynamically computed zoom/scale factors that reach 0 (fit-to-size logic with an empty extent); matrix multiplication chains that degenerate; binding a Matrix from user data containing zeros.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- InvalidMatrixContainsInfinity
- InvalidMatrixContainsNaN
- MatrixNotInvertible
- SR.InvalidMatrixContainsInfinity
- SR.InvalidMatrixContainsNaN
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/58534c3115441a73.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Ink/StrokeCollection.cs:225
return this.ExtendedProperties.Contains(propertyDataId);
}
/// <summary>
/// Applies the specified transform matrix on every stroke in the collection.
/// This method composes this transform with the existing
/// transform on the stroke.</summary>
/// <param name="transformMatrix">The transform to compose against each Stroke</param>
/// <param name="applyToStylusTip">Boolean if true the transform matrix will be applied to StylusTip</param>
/// <remarks>The StrokeCollection does not maintain a separate transform
/// from each Stroke object. Calling Transform on the collection will
/// cause each individual Stroke to be modified.
/// If the StrokesChanged event fires, the changed parameter will be a pointer to 'this'
/// collection, so any changes made to the changed event args will affect 'this' collection.</remarks>
public void Transform(Matrix transformMatrix, bool applyToStylusTip)
{
// Ensure that the transformMatrix is invertible.
if (!transformMatrix.HasInverse)
throw new ArgumentException(SR.MatrixNotInvertible, nameof(transformMatrix));
// if transformMatrix is identity or the StrokeCollection is empty
// then no change will occur anyway
if ( transformMatrix.IsIdentity || Count == 0 )
{
return;
}
// Apply the transform to each strokes
foreach ( Stroke stroke in this )
{
// Presharp gives a warning when get methods might deref a null. It's complaining
// here that 'stroke'' could be null, but StrokeCollection never allows nulls to be added
// so this is not possible
stroke.Transform(transformMatrix, applyToStylusTip);
}
}
View on GitHub (pinned to 81131a70a4)