{"record":{"id":"58534c3115441a73","repo":"dotnet/wpf","slug":"sr-matrixnotinvertible-strokecollection","errorCode":null,"errorMessage":"SR.MatrixNotInvertible","messagePattern":"SR\\.MatrixNotInvertible","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Ink/StrokeCollection.cs","lineNumber":225,"sourceCode":"            return this.ExtendedProperties.Contains(propertyDataId);\n        }\n\n        /// <summary>\n        /// Applies the specified transform matrix on every stroke in the collection.\n        /// This method composes this transform with the existing\n        /// transform on the stroke.</summary>\n        /// <param name=\"transformMatrix\">The transform to compose against each Stroke</param>\n        /// <param name=\"applyToStylusTip\">Boolean if true the transform matrix will be applied to StylusTip</param>\n        /// <remarks>The StrokeCollection does not maintain a separate transform\n        /// from each Stroke object. Calling Transform on the collection will\n        /// cause each individual Stroke to be modified.\n        /// If the StrokesChanged event fires, the changed parameter will be a pointer to 'this'\n        /// collection, so any changes made to the changed event args will affect 'this' collection.</remarks>\n        public void Transform(Matrix transformMatrix, bool applyToStylusTip)\n        {\n            // Ensure that the transformMatrix is invertible.\n            if (!transformMatrix.HasInverse)\n                throw new ArgumentException(SR.MatrixNotInvertible, nameof(transformMatrix));\n\n            // if transformMatrix is identity or the StrokeCollection is empty\n            //      then no change will occur anyway\n            if ( transformMatrix.IsIdentity || Count == 0 )\n            {\n                return;\n            }\n\n            // Apply the transform to each strokes\n            foreach ( Stroke stroke in this )\n            {\n                // Presharp gives a warning when get methods might deref a null.  It's complaining\n                // here that 'stroke'' could be null, but StrokeCollection never allows nulls to be added\n                // so this is not possible\n                stroke.Transform(transformMatrix, applyToStylusTip);\n            }\n        }\n","sourceCodeStart":207,"sourceCodeEnd":243,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Ink/StrokeCollection.cs#L207-L243","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nstrokes.Transform(matrix, true); // matrix has scale (0, 1)\n// after\nif (matrix.HasInverse)\n    strokes.Transform(matrix, true);\nelse\n    strokes.Transform(Matrix.Identity, true);","handlingStrategy":"validation","validationCode":"if (!transformMatrix.HasInverse)\n    transformMatrix = Matrix.Identity; // or fix scale factors\nstrokes.Transform(transformMatrix, applyToStylusTip);","typeGuard":"static bool IsApplicable(Matrix m) => m.HasInverse;","tryCatchPattern":"try { strokes.Transform(matrix, true); }\ncatch (ArgumentException ex) when (ex.Message.Contains(\"invert\")) { strokes.Transform(Matrix.Identity, true); }","preventionTips":["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."],"tags":["wpf","ink","matrix","geometry"],"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"}