SixLabors/ImageSharp · error · InvalidImageContentException

The ANI animation header is truncated.

Error message

The ANI animation header is truncated.

What it means

The 'anih' chunk must be at least AniHeader.Size (36) bytes to hold the full ANI header structure. When the chunk declares a smaller size, the header cannot be parsed completely and InvalidImageContentException is thrown. This catches headers written by non-conformant producers or truncated files.

Solutions

  1. Check the 'anih' chunk size field: it must be >= 36; extend the header to 36 bytes (padding the tail) if you control the writer.
  2. Re-download the file if the chunk payload was truncated in transit.
  3. Re-export the animation with a mainstream tool that always emits the full 36-byte header.

Example fix

// before: [anih size=16][16 bytes]
// after: [anih size=36][36 bytes incl. reserved fields]
Defensive patterns

Strategy: validation

Validate before calling

// Read the anih chunk size field and require >= 36 before decoding
static bool AnihChunkIsFullSize(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 sz >= 36 && fs.Length - fs.Position >= sz;
        fs.Seek((long)((sz + 1) & ~1u), SeekOrigin.Current);
    }
    return false;
}

Try / catch

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

Prevention

When it happens

Trigger: Calling Decode/Identify where the 'anih' chunk's size field is < 36 — e.g. a 12- or 16-byte header from a buggy writer, or a chunk whose declared size exceeds remaining stream bytes so only part is readable.

Common situations: Truncated downloads where the 'anih' chunk size was written correctly but the payload was cut off; minimal header variants from old or hand-rolled ANI writers.

Related errors


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

Appendix: source

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

            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);

        if (this.header.BytesInHeader < AniHeader.Size || this.header.BytesInHeader > chunkSize)
        {
            throw new InvalidImageContentException("The ANI animation header declares an invalid size.");
        }

        this.aniMetadata.Width = this.header.Width;
        this.aniMetadata.Height = this.header.Height;
        this.aniMetadata.BitCount = this.header.BitCount;
        this.aniMetadata.Planes = this.header.Planes;
        this.aniMetadata.DisplayRate = this.header.DisplayRate;
        this.aniMetadata.Flags = this.header.Flags;
    }

View on GitHub (pinned to 59ce6af6fc)