SixLabors/ImageSharp · error · InvalidImageContentException

The ANI RIFF container size is invalid.

Error message

The ANI RIFF container size is invalid.

What it means

The RIFF chunk header declares a payload size, and this check requires it to be at least 4 bytes (the form-type field). A declared size below that cannot describe a valid RIFF form, so InvalidImageContentException is thrown. Note the decoder tolerates real-world files whose size incorrectly includes the 8-byte RIFF preamble — only absurdly small sizes fail here.

Solutions

  1. Inspect bytes 4-8 of the file: fix or regenerate the RIFF size if you control the producing tool.
  2. Re-export the ANI from source frames with a standard cursor authoring tool.
  3. Restore the file from backup or re-download — header-level corruption is usually unrecoverable in place.

Example fix

// before (header bytes): RIFF 00 00 00 00 ACON  (declaredSize=0)
// after: patch the size to payload length
// riffSize = (uint)(fileLength - 8); // 'ACON' + chunks
Defensive patterns

Strategy: validation

Validate before calling

bool HasValidRiffSize(Stream s)
{
    byte[] h = new byte[8];
    if (s.Read(h, 0, 8) != 8) return false;
    s.Position = 0;
    uint size = BinaryPrimitives.ReadUInt32LittleEndian(h.AsSpan(4, 4));
    return size >= 4;
}

Try / catch

try
{
    using Image<Rgba32> img = Image.Load<Rgba32>(path);
}
catch (InvalidImageContentException ex)
{
    logger.LogError(ex, "ANI RIFF header corrupt.");
}

Prevention

When it happens

Trigger: Calling Decode/Identify on an ANI stream whose RIFF size field (bytes 4-8) is less than 4 — typically 0 or a garbage value from a corrupted or fabricated header.

Common situations: Files damaged by bit-rot or partial overwrite of the first sector; synthetic/fuzzed files; files produced by broken custom writers that emit a zero size field.

Related errors


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

Appendix: source

Thrown at src/ImageSharp/Formats/Ani/AniDecoderCore.cs:256

        this.sequence?.Dispose();
        this.rates?.Dispose();
        this.sequence = null;
        this.rates = null;

        long containerStart = stream.Position;
        Span<byte> riffHeader = this.buffer[..AniConstants.RiffHeaderSize];
        ReadExactly(stream, riffHeader, "RIFF header");

        if (!riffHeader[..4].SequenceEqual(AniConstants.RiffFourCc)
            || !riffHeader.Slice(8, 4).SequenceEqual(AniConstants.AniFormTypeFourCc))
        {
            throw new InvalidImageContentException("The stream does not contain an ANI RIFF container.");
        }

        uint declaredSize = BinaryPrimitives.ReadUInt32LittleEndian(riffHeader[4..]);
        if (declaredSize < sizeof(uint))
        {
            throw new InvalidImageContentException("The ANI RIFF container size is invalid.");
        }

        // RIFF size excludes the initial identifier and size field. Some real-world ANI files incorrectly
        // include those eight bytes, so the physical stream length remains the hard read boundary.
        long declaredEnd = checked(containerStart + 8 + declaredSize);
        long containerEnd = Math.Min(declaredEnd, stream.Length);
        bool headerFound = false;

        while (stream.Position + AniConstants.ChunkHeaderSize <= containerEnd)
        {
            AniRiffChunkHeader chunk = this.ReadChunkHeader(stream);
            long dataEnd = GetChunkDataEnd(stream, chunk.Size, containerEnd);

            switch ((AniChunkType)chunk.FourCc)
            {
                case AniChunkType.Header:
                    this.ReadAniHeader(stream, chunk.Size);
                    headerFound = true;

View on GitHub (pinned to 59ce6af6fc)