dotnet/wpf · error · ArgumentException

SR.InvalidMatrixContainsInfinity

Error message

SR.InvalidMatrixContainsInfinity

What it means

Stroke.Transform(Matrix) rejects matrices containing infinite (PositiveInfinity/NegativeInfinity) values via MatrixHelper.ContainsInfinity. Infinite coordinates cannot define a valid transform, so an ArgumentException naming transformMatrix is thrown before modifying the stroke's cached geometry or bounds.

Solutions

  1. Check MatrixHelper.ContainsInfinity (and NaN) before Transform and clamp or correct the source computation
  2. Fix the upstream division producing infinity (guard denominator != 0)
  3. Substitute a bounded matrix (e.g. Matrix.Identity) when the computed transform is non-finite

Example fix

// before
stroke.Transform(zoomMatrix); // may contain Infinity
// after
if (double.IsFinite(zoomMatrix.M11) && zoomMatrix.HasInverse)
    stroke.Transform(zoomMatrix);
Defensive patterns

Strategy: validation

Validate before calling

if (!MatrixHelper.ContainsInfinity(matrix) && matrix.HasInverse) stroke.Transform(matrix);

Type guard

bool IsFiniteMatrix(Matrix m) => double.IsFinite(m.M11) && double.IsFinite(m.M12) && double.IsFinite(m.M21) && double.IsFinite(m.M22) && double.IsFinite(m.OffsetX) && double.IsFinite(m.OffsetY);

Prevention

When it happens

Trigger: Calling stroke.Transform(m) where any matrix coefficient is +/-Infinity — usually from division by a zero scale/dimension or overflow in matrix composition.

Common situations: Dividing by a zero zoom factor computed from UI size; zoom-to-fit math on a zero-area content; numeric overflow in repeated matrix multiplication.

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/808446d6f4a4ad7c. Report an issue: GitHub.

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Ink/Stroke.cs:152

        /// <param name="applyToStylusTip">Boolean if true the transform matrix will be applied to StylusTip</param>
        public virtual void Transform(Matrix transformMatrix, bool applyToStylusTip)
        {
            if (transformMatrix.IsIdentity)
            {
                return;
            }

            if (!transformMatrix.HasInverse)
            {
                throw new ArgumentException(SR.MatrixNotInvertible, nameof(transformMatrix));
            }
            else if ( MatrixHelper.ContainsNaN(transformMatrix))
            {
                throw new ArgumentException(SR.InvalidMatrixContainsNaN, nameof(transformMatrix));
            }
            else if ( MatrixHelper.ContainsInfinity(transformMatrix))
            {
                throw new ArgumentException(SR.InvalidMatrixContainsInfinity, nameof(transformMatrix));
            }
            else
            {
                // we need to force a recaculation of the cached path geometry right after the
                // DrawingAttributes changed, beforet the events are raised.
                _cachedGeometry = null;
                // Set the cached bounds to empty, which will force a re-calculation of the _cachedBounds upon next GetBounds call.
                _cachedBounds = Rect.Empty;

                if (applyToStylusTip)
                {
                    //we use this flag to prevent this method from causing two
                    //invalidates, which causes a good deal of memory thrash when
                    //the strokes are being rendered
                    _delayRaiseInvalidated = true;
                }

                try

View on GitHub (pinned to 81131a70a4)