{"record":{"id":"9ba431744f29ea30","repo":"SixLabors/ImageSharp","slug":"matrix-is-degenerate-check-input-values-9ba431","errorCode":null,"errorMessage":"Matrix is degenerate. Check input values.","messagePattern":"Matrix is degenerate\\. Check input values\\.","errorType":"exception","errorClass":"DegenerateTransformException","httpStatus":null,"severity":"error","filePath":"src/ImageSharp/Processing/ProjectiveTransformBuilder.cs","lineNumber":414,"sourceCode":"    /// <returns>The <see cref=\"Size\"/>.</returns>\n    internal static SizeF GetTransformedSize(Rectangle sourceRectangle, Matrix4x4 matrix)\n        => TransformUtilities.GetRawTransformedSize(matrix, sourceRectangle.Size);\n\n    /// <summary>\n    /// Clears all accumulated transform matrices, resetting the builder to its initial state.\n    /// </summary>\n    /// <returns>The <see cref=\"ProjectiveTransformBuilder\"/>.</returns>\n    public ProjectiveTransformBuilder Clear()\n    {\n        this.transformMatrixFactories.Clear();\n        return this;\n    }\n\n    private static void CheckDegenerate(Matrix4x4 matrix)\n    {\n        if (TransformUtilities.IsDegenerate(matrix))\n        {\n            throw new DegenerateTransformException(\"Matrix is degenerate. Check input values.\");\n        }\n    }\n\n    private ProjectiveTransformBuilder Prepend(Func<Size, Matrix4x4> transformFactory)\n    {\n        this.transformMatrixFactories.Insert(0, transformFactory);\n        return this;\n    }\n\n    private ProjectiveTransformBuilder Append(Func<Size, Matrix4x4> transformFactory)\n    {\n        this.transformMatrixFactories.Add(transformFactory);\n        return this;\n    }\n}\n","sourceCodeStart":396,"sourceCodeEnd":430,"githubUrl":"https://github.com/SixLabors/ImageSharp/blob/59ce6af6fc29027cda277ef62d4d1694a8acce91/src/ImageSharp/Processing/ProjectiveTransformBuilder.cs#L396-L430","documentation":"ProjectiveTransformBuilder.CheckDegenerate runs before matrices are combined (PrependMatrix, AppendMatrix) and again in BuildMatrix, so any intermediate or final composition of appended transforms that becomes degenerate is rejected early with DegenerateTransformException. This prevents silently producing a transform that maps everything to a line/point.","triggerScenarios":"Calling AppendMatrix/PrependMatrix with a degenerate Matrix4x4, or appending factories whose composition (evaluated in BuildMatrix) is degenerate — e.g. appending a scale-0 transform or one that nullifies a prior one.","commonSituations":"Chaining several transform factories where one produces a zero scale; building transforms from user-supplied corner points that are collinear; refactoring builder code and losing a guard on an individual matrix before appending.","solutions":["Validate each Matrix4x4 with Matrix4x4.GetDeterminant() != 0 before Append/Prepend","Ensure each appended factory produces a valid transform for the actual runtime size (factories receive Size at build time)","Catch DegenerateTransformException around BuildMatrix since composed matrices can degenerate even if each part is fine","Reduce the chain to the minimal set of transforms and add them back one at a time to find the offender"],"exampleFix":"// before\nbuilder.AppendMatrix(brokenMatrix); // determinant == 0\n// after\nif (Math.Abs(brokenMatrix.GetDeterminant()) < float.Epsilon)\n{\n    throw new InvalidOperationException(\"Refusing to append degenerate matrix.\");\n}\nbuilder.AppendMatrix(brokenMatrix);","handlingStrategy":"validation","validationCode":"static bool IsNonDegenerate(Matrix4x4 m) => MathF.Abs(m.GetDeterminant()) > 1e-6f;\nforeach (var factory in transformFactories)\n{\n    if (!IsNonDegenerate(factory(size))) throw new InvalidOperationException(\"Degenerate matrix in builder chain.\");\n}","typeGuard":"static bool IsAppendable(Matrix4x4 m) => MathF.Abs(m.GetDeterminant()) > float.Epsilon;","tryCatchPattern":"try\n{\n    var matrix = builder.BuildMatrix(destinationSize);\n}\ncatch (DegenerateTransformException ex)\n{\n    // inspect builder chain; fall back to affine or identity\n    throw;\n}","preventionTips":["Validate each matrix before Append/Prepend, not only the composed result","Ensure transform factories produce valid matrices for the actual runtime Size","Wrap BuildMatrix in try/catch since composition can degenerate even when parts do not","When chaining many transforms, log each intermediate matrix's determinant to isolate the offender"],"tags":["projective-transform","transform-builder","validation"],"backgroundTag":"invalid-argument-value","analyzedSha":"59ce6af6fc29027cda277ef62d4d1694a8acce91","analyzedAt":"2026-09-13T18:34:59.331Z","contentChangedAt":"2026-09-13T18:34:59.331Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}