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

  1. Check matrix.HasInverse before calling Transform and substitute an identity or corrected matrix when it is false.
  2. Fix the source of the zero scale factor (clamp scaleX/scaleY to non-zero minimums in your sizing code).
  3. 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

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


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)