SixLabors/ImageSharp · error · InvalidImageContentException

The ANI file does not contain an animation header.

Error message

The ANI file does not contain an animation header.

What it means

The ANI container must include an 'anih' chunk carrying the animation header (dimensions, bit count, frame count, rate). After walking all chunks within the container bounds, if no 'anih' chunk was encountered the file lacks the mandatory header and InvalidImageContentException is thrown. Without the header the decoder cannot determine frame count, dimensions, or default display rate.

Solutions

  1. Verify with a RIFF chunk dumper that an 'anih' chunk exists inside the ACON form; rebuild the file if it is missing.
  2. Check the RIFF declared size — if it cuts off before the 'anih' chunk, patch the size or re-export the file.
  3. Re-create the ANI with a standard tool so the mandatory 'anih' chunk is emitted first.

Example fix

// before: ACON { [seq ][rate ][fram...] } — no anih
// after: ACON { [anih(36 bytes)][seq ][rate ][fram...] }
Defensive patterns

Strategy: validation

Validate before calling

// Scan top-level RIFF chunks for an 'anih' before decoding
static bool HasAnihChunk(string path)
{
    using var fs = File.OpenRead(path);
    Span<byte> buf = stackalloc byte[8];
    fs.Seek(12, SeekOrigin.Begin);
    while (fs.Read(buf) == 8)
    {
        uint sz = BinaryPrimitives.ReadUInt32LittleEndian(buf.Slice(4, 4));
        if (buf.Slice(0, 4).SequenceEqual("anih"u8)) return true;
        fs.Seek((long)((sz + 1) & ~1u), SeekOrigin.Current);
    }
    return false;
}

Try / catch

try
{
    using Image<Rgba32> img = Image.Load<Rgba32>(path);
}
catch (InvalidImageContentException)
{
    ReportMissingAnih(path);
}

Prevention

When it happens

Trigger: Calling Decode/Identify on an ANI RIFF container that contains e.g. only 'seq ', 'rate', or 'fram' chunks but no 'anih' chunk; files where the 'anih' chunk lies beyond the declared container end and is therefore never reached.

Common situations: Custom ANI writers that emit frame data but forget the header; files truncated after the metadata chunks; seq/rate chunks reordered ahead of a clipped header.

Related errors


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

Appendix: source

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

                    break;
                case AniChunkType.Sequence:
                    // Ordering and timing affect presentation, not pixel decoding, so malformed chunks follow ancillary handling.
                    this.ExecuteAncillarySegmentAction(() => this.ReadUInt32Values(stream, chunk.Size, "sequence", ref this.sequence));
                    break;
                case AniChunkType.Rate:
                    this.ExecuteAncillarySegmentAction(() => this.ReadUInt32Values(stream, chunk.Size, "rate", ref this.rates));
                    break;
                case AniChunkType.List:
                    this.ReadList(stream, dataEnd);
                    break;
            }

            stream.Position = GetPaddedEnd(dataEnd, chunk.Size, containerEnd);
        }

        if (!headerFound)
        {
            throw new InvalidImageContentException("The ANI file does not contain an animation header.");
        }
    }

    /// <summary>
    /// Parses the mandatory 36-byte ANI header and copies its observable values to image metadata.
    /// </summary>
    /// <param name="stream">The ANI stream.</param>
    /// <param name="chunkSize">The ANI header chunk size.</param>
    private void ReadAniHeader(BufferedReadStream stream, uint chunkSize)
    {
        if (chunkSize < AniHeader.Size)
        {
            throw new InvalidImageContentException("The ANI animation header is truncated.");
        }

        Span<byte> data = this.buffer;
        ReadExactly(stream, data, "ANI header");
        this.header = AniHeader.Parse(data);

View on GitHub (pinned to 59ce6af6fc)