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
- Verify with a RIFF chunk dumper that an 'anih' chunk exists inside the ACON form; rebuild the file if it is missing.
- Check the RIFF declared size — if it cuts off before the 'anih' chunk, patch the size or re-export the file.
- 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
- Never emit ANI frames without a preceding 'anih' chunk.
- Ensure the RIFF declared size covers the whole form so the 'anih' chunk is reachable.
- Validate produced ANI files with a chunk dumper in CI for cursor-asset pipelines.
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
- The stream does not contain an ANI RIFF container.
- The ANI RIFF container size is invalid.
- The ANI animation header is truncated.
- The ANI animation header declares an invalid size.
- The ANI file contains a truncated RIFF list.
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)