SixLabors/ImageSharp · error · NotSupportedException

Invalid or unsupported bit depth. Was

Error message

Invalid or unsupported bit depth. Was '{this.BitDepth}'.

What it means

PngHeader.Validate throws this NotSupportedException when the IHDR bit depth is not among the depths the PNG specification allows for the chunk's color type (e.g. only 1/2/4/8/16 for grayscale, only 8/16 for RGB). The color type lookup succeeded, but the paired BitDepth value is not in PngConstants.ColorTypes[ColorType], so the image cannot be decoded.

Solutions

  1. Re-save the image with a standard tool (viewers, ImageSharp) so encoder picks a valid bit depth/color type combination.
  2. Verify the file integrity and re-download if the source may be corrupted.
  3. Catch NotSupportedException around the load call and handle the invalid file gracefully.
  4. If a custom encoder produced the file, fix it to emit only depths valid for the chosen color type.

Example fix

// before
using var image = Image.Load("16bit-palette.png"); // palette + 16-bit is illegal
// after
try
{
    using var image = Image.Load("16bit-palette.png");
}
catch (NotSupportedException)
{
    using var image = Image.Load("16bit-palette-converted.png"); // re-exported as 8-bit RGB
}
Defensive patterns

Strategy: try-catch

Validate before calling

// valid bit depths per color type per PNG spec
static readonly Dictionary<byte, byte[]> Valid = new()
{
    [0] = new byte[] { 1, 2, 4, 8, 16 },
    [2] = new byte[] { 8, 16 },
    [3] = new byte[] { 1, 2, 4, 8 },
    [4] = new byte[] { 8, 16 },
    [6] = new byte[] { 8, 16 }
};
// check: Valid[colorType].Contains(bitDepth)

Type guard

static bool IsValidBitDepthForColorType(byte colorType, byte bitDepth) =>
    colorType switch
    {
        0 => bitDepth is 1 or 2 or 4 or 8 or 16,
        2 or 4 or 6 => bitDepth is 8 or 16,
        3 => bitDepth is 1 or 2 or 4 or 8,
        _ => false
    };

Try / catch

try
{
    using var image = Image.Load(pngStream);
}
catch (NotSupportedException ex) when (ex.Message.Contains("bit depth"))
{
    using var repaired = ReExportWithStandardEncoder(originalPath); // re-save via another tool
}

Prevention

When it happens

Trigger: Decoding a PNG whose IHDR combines a legal color type with an illegal bit depth — for example color type 3 (palette) with bit depth 16, or a fuzzed/corrupted bit-depth byte.

Common situations: Files produced by non-conformant encoders, hand-crafted or fuzzed PNGs, corruption during transfer, or converting images with a tool that sets bit depth independently of color type.

Related errors


AI-assisted analysis of SixLabors/ImageSharp@59ce6af6fc (2026-09-13). Data as JSON: /api/errors/f8fcbcd517036cff. Report an issue: GitHub.

Appendix: source

Thrown at src/ImageSharp/Formats/Png/Chunks/PngHeader.cs:98

    /// </summary>
    public PngInterlaceMode InterlaceMethod { get; }

    /// <summary>
    /// Validates the png header.
    /// </summary>
    /// <exception cref="NotSupportedException">
    /// Thrown if the image does pass validation.
    /// </exception>
    public void Validate()
    {
        if (!PngConstants.ColorTypes.TryGetValue(this.ColorType, out byte[] supportedBitDepths))
        {
            throw new NotSupportedException($"Invalid or unsupported color type. Was '{this.ColorType}'.");
        }

        if (supportedBitDepths.AsSpan().IndexOf(this.BitDepth) == -1)
        {
            throw new NotSupportedException($"Invalid or unsupported bit depth. Was '{this.BitDepth}'.");
        }

        if (this.FilterMethod != 0)
        {
            throw new NotSupportedException($"Invalid filter method. Expected 0. Was '{this.FilterMethod}'.");
        }

        // The png specification only defines 'None' and 'Adam7' as interlaced methods.
        if (this.InterlaceMethod is not PngInterlaceMode.None and not PngInterlaceMode.Adam7)
        {
            throw new NotSupportedException($"Invalid interlace method. Expected 'None' or 'Adam7'. Was '{this.InterlaceMethod}'.");
        }
    }

    /// <summary>
    /// Writes the header to the given buffer.
    /// </summary>
    /// <param name="buffer">The buffer to write to.</param>

View on GitHub (pinned to 59ce6af6fc)