{"record":{"id":"83065030155eb5ba","repo":"dotnet/wpf","slug":"sr-invalidmatrixcontainsnan","errorCode":null,"errorMessage":"SR.InvalidMatrixContainsNaN","messagePattern":"SR\\.InvalidMatrixContainsNaN","errorType":"validation","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Ink/Stroke.cs","lineNumber":148,"sourceCode":"\n\n        /// <summary>Transforms the ink and also changes the StylusTip</summary>\n        /// <param name=\"transformMatrix\">Matrix to transform the stroke by</param>\n        /// <param name=\"applyToStylusTip\">Boolean if true the transform matrix will be applied to StylusTip</param>\n        public virtual void Transform(Matrix transformMatrix, bool applyToStylusTip)\n        {\n            if (transformMatrix.IsIdentity)\n            {\n                return;\n            }\n\n            if (!transformMatrix.HasInverse)\n            {\n                throw new ArgumentException(SR.MatrixNotInvertible, nameof(transformMatrix));\n            }\n            else if ( MatrixHelper.ContainsNaN(transformMatrix))\n            {\n                throw new ArgumentException(SR.InvalidMatrixContainsNaN, nameof(transformMatrix));\n            }\n            else if ( MatrixHelper.ContainsInfinity(transformMatrix))\n            {\n                throw new ArgumentException(SR.InvalidMatrixContainsInfinity, nameof(transformMatrix));\n            }\n            else\n            {\n                // we need to force a recaculation of the cached path geometry right after the\n                // DrawingAttributes changed, beforet the events are raised.\n                _cachedGeometry = null;\n                // Set the cached bounds to empty, which will force a re-calculation of the _cachedBounds upon next GetBounds call.\n                _cachedBounds = Rect.Empty;\n\n                if (applyToStylusTip)\n                {\n                    //we use this flag to prevent this method from causing two\n                    //invalidates, which causes a good deal of memory thrash when\n                    //the strokes are being rendered","sourceCodeStart":130,"sourceCodeEnd":166,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Ink/Stroke.cs#L130-L166","documentation":"Stroke.Transform(Matrix) rejects matrices containing NaN values via MatrixHelper.ContainsNaN. A NaN matrix has no meaningful geometric interpretation and would corrupt cached geometry and bounds, so an ArgumentException naming transformMatrix is thrown before any state is modified.","triggerScenarios":"Calling stroke.Transform(m) where any of m's six doubles is NaN — typically the result of 0/0, Math.Atan of invalid input, or a transform derived from a divide-by-zero scale computation.","commonSituations":"Data-binding or measurement code producing NaN widths/heights (e.g. NaN from ActualWidth before layout) that flow into matrix construction; deserializing matrices from corrupted data.","solutions":["Validate with MatrixHelper.ContainsNaN (or double.IsNaN on M11..OffsetY) before calling Transform and reject/repair the source values","Trace upstream arithmetic (divisions, layout values) that produce NaN and fix at the source","Replace the NaN matrix with a valid default (e.g. Matrix.Identity) when NaN indicates missing data"],"exampleFix":"// before\nstroke.Transform(computedMatrix); // may contain NaN\n// after\nif (!MatrixHelper.ContainsNaN(computedMatrix) && !MatrixHelper.ContainsInfinity(computedMatrix))\n    stroke.Transform(computedMatrix);","handlingStrategy":"validation","validationCode":"bool ok = !MatrixHelper.ContainsNaN(matrix) && !MatrixHelper.ContainsInfinity(matrix) && matrix.HasInverse;","typeGuard":"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);","tryCatchPattern":null,"preventionTips":["Trace NaN sources upstream: division by zero, NaN layout values (ActualWidth during layout)","Reject non-finite computed transforms at the boundary where they are built","Test transform math with edge-case inputs (zero sizes)"],"tags":["wpf","ink","matrix","nan","argument-exception"],"backgroundTag":"invalid-argument-value","analyzedSha":"81131a70a4c573cd62748a5c36908fc4d662daa9","analyzedAt":"2026-09-14T10:12:48.479Z","contentChangedAt":"2026-09-14T10:12:48.479Z","schemaVersion":2},"datasetVersion":"2026-09-21T21:30:21.729Z"}