SixLabors/ImageSharp · error · NotSupportedException
Bit depth is not supported or not valid.
Error message
Bit depth is not supported or not valid.
What it means
PngEncoderCore's bit-depth selection helper throws this NotSupportedException when the chosen (colorType, bitDepth) pair is not in PngConstants.ColorTypes — i.e. the depth is not legal for that PNG color type (for example 16-bit palette, or 1/2/4-bit RGB). It is the encoder-side mirror of the IHDR validation the decoder performs.
Solutions
- Use a valid color type/bit depth combination (palette: 1/2/4/8; grayscale: 1/2/4/8/16; gray-alpha, RGB, RGBA: 8 or 16).
- Omit BitDepth (leave default) and let the encoder derive a valid depth from the pixel type.
- If palette output is needed at 8-bit, set BitDepth = Bit8, or switch ColorType to Rgb/RgbWithAlpha for 16-bit.
- Log and validate the encoder options against PngConstants.ColorTypes before calling Save.
Example fix
// before
var encoder = new PngEncoder { ColorType = PngColorType.Palette, BitDepth = PngBitDepth.Bit16 };
image.SaveAsPng("out.png", encoder); // throws
// after
var encoder = new PngEncoder { ColorType = PngColorType.Palette, BitDepth = PngBitDepth.Bit8 };
image.SaveAsPng("out.png", encoder); Defensive patterns
Strategy: validation
Validate before calling
// validate encoder options against the spec table before saving
static bool IsValidPngDepth(PngColorType t, PngBitDepth d) => t switch
{
PngColorType.Palette => d is PngBitDepth.Bit1 or PngBitDepth.Bit2 or PngBitDepth.Bit4 or PngBitDepth.Bit8,
PngColorType.Grayscale => true,
_ => d is PngBitDepth.Bit8 or PngBitDepth.Bit16
}; Type guard
static bool IsValidPngDepth(PngColorType t, PngBitDepth d) =>
t == PngColorType.Palette
? d is PngBitDepth.Bit1 or PngBitDepth.Bit2 or PngBitDepth.Bit4 or PngBitDepth.Bit8
: d is PngBitDepth.Bit8 or PngBitDepth.Bit16; Try / catch
try
{
image.SaveAsPng(path, encoder);
}
catch (NotSupportedException ex) when (ex.Message.Contains("Bit depth"))
{
image.SaveAsPng(path, new PngEncoder()); // defaults derive a valid depth
} Prevention
- Leave PngEncoder.BitDepth unset and let the encoder derive it from the pixel type.
- For palette output always use 1/2/4/8-bit depths; reserve 16-bit for grayscale/RGB/RGBA.
- Centralize encoder option construction so invalid colorType+depth pairs cannot be assembled ad hoc.
When it happens
Trigger: Saving to PNG with PngEncoder BitDepth/ColorType options that combine illegally, e.g. `new PngEncoder { ColorType = PngColorType.Palette, BitDepth = PngBitDepth.Bit16 }`, or quantized 1/2/4-bit output requested for an unsupported color type.
Common situations: Hand-built PngEncoder option sets, porting settings from another library's API, or blindly reusing previously captured encoder options across differently processed images.
Understand the failure class
Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.
Related errors
- ANI bitmap resources require a supported bit depth.
- Restart interval must be in [0..65535] range.
- Invalid or unsupported bit depth. Was
- No encoder was found for extension
- maxDegreeOfParallelism
AI-assisted analysis of SixLabors/ImageSharp@59ce6af6fc (2026-09-13).
Data as JSON: /api/errors/41133fab3dcb463f.
Report an issue: GitHub.
Appendix: source
Thrown at src/ImageSharp/Formats/Png/PngEncoderCore.cs:1797
byte quantizedBits = (byte)Numerics.Clamp(ColorNumerics.GetBitsNeededForColorDepth(quantizedFrame!.Palette.Length), 1, 8);
byte bits = Math.Max(bitDepth, quantizedBits);
// Png only supports in four pixel depths: 1, 2, 4, and 8 bits when using the PLTE chunk
// We check again for the bit depth as the bit depth of the color palette from a given quantizer might not
// be within the acceptable range.
bits = bits switch
{
3 => 4,
>= 5 and <= 7 => 8,
_ => bits
};
bitDepth = bits;
}
if (Array.IndexOf(PngConstants.ColorTypes[colorType], bitDepth) < 0)
{
throw new NotSupportedException("Bit depth is not supported or not valid.");
}
return bitDepth;
}
/// <summary>
/// Calculates the correct number of bytes per pixel for the given color type.
/// </summary>
/// <param name="pngColorType">The color type.</param>
/// <param name="use16Bit">Whether to use 16 bits per component.</param>
/// <returns>Bytes per pixel.</returns>
private static int CalculateBytesPerPixel(PngColorType? pngColorType, bool use16Bit)
=> pngColorType switch
{
PngColorType.Grayscale => use16Bit ? 2 : 1,
PngColorType.GrayscaleWithAlpha => use16Bit ? 4 : 2,
PngColorType.Palette => 1,
PngColorType.Rgb => use16Bit ? 6 : 3,View on GitHub (pinned to 59ce6af6fc)