SixLabors/ImageSharp · error · InvalidImageContentException
Invalid compressed PNG metadata.
Error message
Invalid compressed PNG metadata.
What it means
PngDecoderCore throws this InvalidImageContentException when a compressed ancillary PNG chunk (e.g. iCCP, tEXt/zTXt/iTXt) fails zlib decompression and SegmentIntegrityHandling is Strict. The strict policy treats undecompressable metadata as fatal instead of dropping the segment; in non-strict modes the corrupt chunk's content is discarded (uncompressedBytesArray = []) and decoding continues.
Solutions
- Set SegmentIntegrityHandling to a non-strict value (e.g. Ignore/Omit) if losing ancillary metadata (ICC profile, text) is acceptable.
- Remove or repair the corrupt metadata chunk in the source file (e.g. strip iCCP with a PNG utility).
- Re-export the image so metadata chunks are rewritten with valid zlib streams.
- Wrap decode in try-catch and fall back to a relaxed-options decode on failure.
Example fix
// before
var options = new DecoderOptions { SegmentIntegrityHandling = SegmentIntegrityHandling.Strict };
using var image = Image.Load(options, "meta.png");
// after
try
{
var strict = new DecoderOptions { SegmentIntegrityHandling = SegmentIntegrityHandling.Strict };
using var image = Image.Load(strict, "meta.png");
}
catch (InvalidImageContentException)
{
var relaxed = new DecoderOptions { SegmentIntegrityHandling = SegmentIntegrityHandling.Omit };
using var image = Image.Load(relaxed, "meta.png"); // skip corrupt metadata chunk
} Defensive patterns
Strategy: try-catch
Validate before calling
// decode strict first, fall back to relaxed handling when metadata is corrupt
var strict = new DecoderOptions { SegmentIntegrityHandling = SegmentIntegrityHandling.Strict }; Try / catch
try
{
using var image = Image.Load(strictOptions, path);
}
catch (InvalidImageContentException ex) when (ex.Message == "Invalid compressed PNG metadata.")
{
var relaxed = new DecoderOptions { SegmentIntegrityHandling = SegmentIntegrityHandling.Omit };
using var image = Image.Load(relaxed, path); // drops the corrupt iCCP/text chunk
} Prevention
- Only enable SegmentIntegrityHandling.Strict when corrupt metadata must abort processing (security pipelines).
- Strip iCCP/zTXt chunks from untrusted files before strict decoding.
- Prefer re-exporting files whose ancillary chunks fail decompression.
When it happens
Trigger: Decoding a PNG with a corrupt or unsupported compressed metadata chunk while PngDecoderOptions.SegmentIntegrityHandling == SegmentIntegrityHandling.Strict; e.g. a truncated zTXt chunk or invalid zlib stream in iCCP.
Common situations: Files truncated mid-chunk, metadata written by tools using non-standard deflate data, deliberately malformed inputs in security-sensitive pipelines, or toggling Strict handling on untrusted image sets.
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
- Invalid window size for ZLIB header: cinfo=
- Bad method for ZLIB header: cmf=
- CICP matrix coefficients other than Identity are not…
- {message}
- Iptc profile size exceeds limit of
AI-assisted analysis of SixLabors/ImageSharp@59ce6af6fc (2026-09-13).
Data as JSON: /api/errors/51ef8f6536ac2bf0.
Report an issue: GitHub.
Appendix: source
Thrown at src/ImageSharp/Formats/Png/PngDecoderCore.cs:2011
{
uncompressedBytesArray = [];
return false;
}
memoryStreamOutput.Write(destUncompressedData[..bytesRead]);
bytesRead = inflateStream.CompressedStream.Read(destUncompressedData);
}
uncompressedBytesArray = memoryStreamOutput.ToArray();
return true;
}
catch (InvalidDataException ex)
{
// ICC and text chunks are already bounded in memory, so rejecting their compressed contents
// does not lose the next chunk boundary. Apply the ancillary policy without keeping partial output.
if (this.Options.SegmentIntegrityHandling == SegmentIntegrityHandling.Strict)
{
throw new InvalidImageContentException("Invalid compressed PNG metadata.", ex);
}
uncompressedBytesArray = [];
return false;
}
}
}
/// <summary>
/// Compares two ReadOnlySpan<char>s in a case-insensitive method.
/// This is only needed because older frameworks are missing the extension method.
/// </summary>
/// <param name="span1">The first <see cref="Span{T}"/> to compare.</param>
/// <param name="span2">The second <see cref="Span{T}"/> to compare.</param>
/// <returns>True if the spans were identical, false otherwise.</returns>
private static bool StringEqualsInsensitive(ReadOnlySpan<char> span1, ReadOnlySpan<char> span2)
=> span1.Equals(span2, StringComparison.OrdinalIgnoreCase);
View on GitHub (pinned to 59ce6af6fc)