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

  1. Set SegmentIntegrityHandling to a non-strict value (e.g. Ignore/Omit) if losing ancillary metadata (ICC profile, text) is acceptable.
  2. Remove or repair the corrupt metadata chunk in the source file (e.g. strip iCCP with a PNG utility).
  3. Re-export the image so metadata chunks are rewritten with valid zlib streams.
  4. 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

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


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&lt;char&gt;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)