SixLabors/ImageSharp · error · DegenerateTransformException
Matrix is degenerate. Check input values.
Error message
Matrix is degenerate. Check input values.
What it means
The ProjectiveTransformProcessor constructor validates that the 4x4 projective matrix is non-degenerate — a degenerate matrix collapses the projective plane and produces an unrenderable mapping. TransformUtilities.IsDegenerate guards this in the constructor, throwing DegenerateTransformException before sampling starts.
Solutions
- Check Matrix4x4.GetDeterminant() before constructing the processor
- Correct or clamp the matrix values that produce the degenerate result
- Catch DegenerateTransformException and substitute a fallback (identity or affine) transform
- When building matrices from points, ensure they form a proper quad with non-zero area
Example fix
// before
var m = new Matrix4x4(
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 0, 0, // last row zeroed => degenerate
0, 0, 0, 1);
image.Mutate(x => x.Transform(new ProjectiveTransformBuilder().AppendMatrix(m)));
// after
var m = new Matrix4x4(
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1); // ensure non-zero determinant
image.Mutate(x => x.Transform(new ProjectiveTransformBuilder().AppendMatrix(m))); Defensive patterns
Strategy: validation
Validate before calling
static bool IsNonDegenerate(Matrix4x4 m) => MathF.Abs(m.GetDeterminant()) > 1e-6f;
if (!IsNonDegenerate(matrix)) throw new InvalidOperationException("Projective matrix is degenerate."); Type guard
static bool IsUsableProjectiveMatrix(Matrix4x4 m) => !float.IsNaN(m.GetDeterminant()) && MathF.Abs(m.GetDeterminant()) > float.Epsilon;
Try / catch
try
{
image.Mutate(x => x.Transform(new ProjectiveTransformBuilder().AppendMatrix(m)));
}
catch (DegenerateTransformException ex)
{
// substitute identity or last-known-good matrix
throw;
} Prevention
- Validate matrix determinant before constructing ProjectiveTransformProcessor
- Avoid zeroing out rows or columns of hand-built matrices
- Build matrices via ProjectiveTransformBuilder.Append* helpers with validated point pairs
- When concatenating, re-check the determinant of the composed matrix
When it happens
Trigger: Creating a ProjectiveTransformProcessor or calling projective Mutate/Transform overloads with a matrix whose determinant (or relevant projective invariant) is zero, typically from a hand-built Matrix4x4 or from degenerate point correspondences.
Common situations: Hard-coded projective matrices with a zero row/column; concatenating transforms that cancel; building projective matrices from 4 coplanar source points via GaussianEliminationSolver (see the singular-matrix error at the same call depth).
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
- Matrix is degenerate. Check input values.
- Matrix is degenerate. Check input values.
- ANI bitmap resources require a supported bit depth.
- ANI bitmap resources require exactly one color plane.
- Invalid gif colormap size
AI-assisted analysis of SixLabors/ImageSharp@59ce6af6fc (2026-09-13).
Data as JSON: /api/errors/42b0e4ccf24bae8d.
Report an issue: GitHub.
Appendix: source
Thrown at src/ImageSharp/Processing/Processors/Transforms/Linear/ProjectiveTransformProcessor.cs:26
/// <summary>
/// Defines a projective transformation applicable to an <see cref="Image"/>.
/// </summary>
public sealed class ProjectiveTransformProcessor : CloningImageProcessor
{
/// <summary>
/// Initializes a new instance of the <see cref="ProjectiveTransformProcessor"/> class.
/// </summary>
/// <param name="matrix">The transform matrix.</param>
/// <param name="sampler">The sampler to perform the transform operation.</param>
/// <param name="targetDimensions">The target dimensions.</param>
public ProjectiveTransformProcessor(Matrix4x4 matrix, IResampler sampler, Size targetDimensions)
{
Guard.NotNull(sampler, nameof(sampler));
Guard.MustBeValueType(sampler);
if (TransformUtilities.IsDegenerate(matrix))
{
throw new DegenerateTransformException("Matrix is degenerate. Check input values.");
}
this.Sampler = sampler;
this.TransformMatrix = matrix;
this.DestinationSize = targetDimensions;
}
/// <summary>
/// Gets the sampler to perform interpolation of the transform operation.
/// </summary>
public IResampler Sampler { get; }
/// <summary>
/// Gets the matrix used to supply the projective transform.
/// </summary>
public Matrix4x4 TransformMatrix { get; }
/// <summary>View on GitHub (pinned to 59ce6af6fc)