SixLabors/ImageSharp · error · InvalidIccProfileException

Curve has to be either "IccTypeSignature.Curve" or…

Error message

Curve has to be either "IccTypeSignature.Curve" or "IccTypeSignature.ParametricCurve" for LutAToB- and LutBToA-TagDataEntries

What it means

ImageSharp's ICC profile writer requires that every curve in a LutAToB or LutBToA tag data entry has a type signature of either Curve or ParametricCurve. When writing such an entry, WriteCurves iterates the curve list and throws InvalidIccProfileException if any entry has another signature (e.g. a multiLocalizedUnicode or text entry accidentally placed in the curve list).

Solutions

  1. Inspect the curves arrays on the LutAtoB/LutBToA entry and remove or replace any entry whose Signature is not Curve or ParametricCurve
  2. Convert curve data into a proper IccCurveTagDataEntry or IccParametricCurveTagDataEntry before assigning it to the entry
  3. If the profile came from an external source, re-export it from a conformant tool so the Lut tag contains only curve entries
  4. Wrap ICC writing in a try-catch on InvalidIccProfileException to surface a clear message about the offending entry

Example fix

// before
var entry = new IccLutAtoBTagDataEntry(..., curvesB: new IccTagDataEntry[] { someTextEntry });
// after
var curveEntry = new IccCurveTagDataEntry(curveData);
var entry = new IccLutAtoBTagDataEntry(..., curvesB: new IccTagDataEntry[] { curveEntry });
Defensive patterns

Strategy: validation

Validate before calling

bool valid = entry.CurvesM?.All(c => c.Signature is IccTypeSignature.Curve or IccTypeSignature.ParametricCurve) ?? true
    && (entry.CurvesA?.All(c => c.Signature is IccTypeSignature.Curve or IccTypeSignature.ParametricCurve) ?? true)
    && (entry.CurvesB?.All(c => c.Signature is IccTypeSignature.Curve or IccTypeSignature.ParametricCurve) ?? true);

Type guard

static bool IsCurveEntry(IccTagDataEntry e) => e.Signature is IccTypeSignature.Curve or IccTypeSignature.ParametricCurve;

Try / catch

try { writer.WriteTagDataEntry(lutEntry); } catch (InvalidIccProfileException ex) { log.Error(ex, "Non-curve entry in Lut tag"); throw; }

Prevention

When it happens

Trigger: Calling WriteTagDataEntry on an IccLutAtoBTagDataEntry or IccLutBToATagDataEntry whose ATobB curves collection (curvesM, curvesA, or curvesB) contains an entry whose IccTagDataEntry.Signature is not IccTypeSignature.Curve or IccTypeSignature.ParametricCurve.

Common situations: Hand-constructing ICC LutAtoB/BToA entries with a mis-typed entry in the curves arrays; parsing a non-conformant ICC profile and re-serializing it; copying entries from one profile's tag table into another's Lut curves list.

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/b8a823ce7d7e8b9b. Report an issue: GitHub.

Appendix: source

Thrown at src/ImageSharp/Metadata/Profiles/ICC/DataWriter/IccDataWriter.cs:220

            this.dataStream.WriteByte(data[i]);
        }

        return length;
    }

    /// <summary>
    /// Writes curve data
    /// </summary>
    /// <param name="curves">The curves to write</param>
    /// <returns>The number of bytes written</returns>
    private int WriteCurves(IccTagDataEntry[] curves)
    {
        int count = 0;
        foreach (IccTagDataEntry curve in curves)
        {
            if (curve.Signature != IccTypeSignature.Curve && curve.Signature != IccTypeSignature.ParametricCurve)
            {
                throw new InvalidIccProfileException($"Curve has to be either \"{nameof(IccTypeSignature)}.{nameof(IccTypeSignature.Curve)}\" or" +
                    $" \"{nameof(IccTypeSignature)}.{nameof(IccTypeSignature.ParametricCurve)}\" for LutAToB- and LutBToA-TagDataEntries");
            }

            count += this.WriteTagDataEntry(curve);
            count += this.WritePadding();
        }

        return count;
    }

    private void Dispose(bool disposing)
    {
        if (!this.isDisposed)
        {
            if (disposing)
            {
                this.dataStream?.Dispose();
            }

View on GitHub (pinned to 59ce6af6fc)