SixLabors/ImageSharp · error · DegenerateTransformException

Matrix is degenerate. Check input values.

Error message

Matrix is degenerate. Check input values.

What it means

The AffineTransformProcessor constructor validates that the affine transform matrix is not degenerate — i.e. it collapses space (zero determinant / non-invertible), so no meaningful source-to-destination mapping exists. TransformUtilities.IsDegenerate performs this check and DegenerateTransformException is thrown before any pixels are processed.

Solutions

  1. Check the matrix before passing it: ensure it has a non-zero determinant (Matrix4x4.GetDeterminant() != 0)
  2. Fix the source of the matrix — e.g. clamp scale factors away from 0
  3. Catch DegenerateTransformException and fall back to an identity or last-known-good transform
  4. Validate concatenated matrices after each append/prepend when building transforms dynamically

Example fix

// before
var matrix = Matrix3x2.CreateScale(scaleX, scaleY); // scaleX == 0 from config
image.Mutate(x => x.Transform(matrix));
// after
if (Math.Abs(Matrix3x2.CreateScale(scaleX, scaleY).GetDeterminant()) < float.Epsilon)
{
    throw new InvalidOperationException("Affine matrix is degenerate; check scale factors.");
}
image.Mutate(x => x.Transform(Matrix3x2.CreateScale(scaleX, scaleY)));
Defensive patterns

Strategy: validation

Validate before calling

static bool IsNonDegenerate(Matrix4x4 m) => MathF.Abs(m.GetDeterminant()) > 1e-6f;
if (!IsNonDegenerate(matrix)) throw new InvalidOperationException("Affine matrix is degenerate.");

Type guard

static bool IsUsableAffineTransform(Matrix4x4 m) => !float.IsNaN(m.GetDeterminant()) && MathF.Abs(m.GetDeterminant()) > float.Epsilon;

Try / catch

try
{
    image.Mutate(x => x.Transform(affineMatrix));
}
catch (DegenerateTransformException ex)
{
    // fall back to identity or last known good matrix
    throw;
}

Prevention

When it happens

Trigger: Creating an AffineTransformProcessor (or calling AffineTransformBuilder-driven Mutate/Transform overloads) with a matrix whose determinant is zero, e.g. a scale of 0 on an axis or a projection onto a line.

Common situations: Building transform matrices from user input or configuration where a scale factor is 0; concatenating matrices that cancel each other out; computing matrices at runtime (from fit-to-size math) that produce a singular result.

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 SixLabors/ImageSharp@59ce6af6fc (2026-09-13). Data as JSON: /api/errors/175479132daed28c. Report an issue: GitHub.

Appendix: source

Thrown at src/ImageSharp/Processing/Processors/Transforms/Linear/AffineTransformProcessor.cs:26

/// <summary>
/// Defines an affine transformation applicable on an <see cref="Image"/>.
/// </summary>
public class AffineTransformProcessor : CloningImageProcessor
{
    /// <summary>
    /// Initializes a new instance of the <see cref="AffineTransformProcessor"/> 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 AffineTransformProcessor(Matrix3x2 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 affine transform.
    /// </summary>
    public Matrix3x2 TransformMatrix { get; }

    /// <summary>

View on GitHub (pinned to 59ce6af6fc)