{"record":{"id":"e57edc6e97d07f19","repo":"SixLabors/ImageSharp","slug":"the-ani-file-does-not-contain-an-animation-header","errorCode":null,"errorMessage":"The ANI file does not contain an animation header.","messagePattern":"The ANI file does not contain an animation header\\.","errorType":"exception","errorClass":"InvalidImageContentException","httpStatus":null,"severity":"error","filePath":"src/ImageSharp/Formats/Ani/AniDecoderCore.cs","lineNumber":293,"sourceCode":"                    break;\n                case AniChunkType.Sequence:\n                    // Ordering and timing affect presentation, not pixel decoding, so malformed chunks follow ancillary handling.\n                    this.ExecuteAncillarySegmentAction(() => this.ReadUInt32Values(stream, chunk.Size, \"sequence\", ref this.sequence));\n                    break;\n                case AniChunkType.Rate:\n                    this.ExecuteAncillarySegmentAction(() => this.ReadUInt32Values(stream, chunk.Size, \"rate\", ref this.rates));\n                    break;\n                case AniChunkType.List:\n                    this.ReadList(stream, dataEnd);\n                    break;\n            }\n\n            stream.Position = GetPaddedEnd(dataEnd, chunk.Size, containerEnd);\n        }\n\n        if (!headerFound)\n        {\n            throw new InvalidImageContentException(\"The ANI file does not contain an animation header.\");\n        }\n    }\n\n    /// <summary>\n    /// Parses the mandatory 36-byte ANI header and copies its observable values to image metadata.\n    /// </summary>\n    /// <param name=\"stream\">The ANI stream.</param>\n    /// <param name=\"chunkSize\">The ANI header chunk size.</param>\n    private void ReadAniHeader(BufferedReadStream stream, uint chunkSize)\n    {\n        if (chunkSize < AniHeader.Size)\n        {\n            throw new InvalidImageContentException(\"The ANI animation header is truncated.\");\n        }\n\n        Span<byte> data = this.buffer;\n        ReadExactly(stream, data, \"ANI header\");\n        this.header = AniHeader.Parse(data);","sourceCodeStart":275,"sourceCodeEnd":311,"githubUrl":"https://github.com/SixLabors/ImageSharp/blob/59ce6af6fc29027cda277ef62d4d1694a8acce91/src/ImageSharp/Formats/Ani/AniDecoderCore.cs#L275-L311","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before: ACON { [seq ][rate ][fram...] } — no anih\n// after: ACON { [anih(36 bytes)][seq ][rate ][fram...] }","handlingStrategy":"validation","validationCode":"// Scan top-level RIFF chunks for an 'anih' before decoding\nstatic bool HasAnihChunk(string path)\n{\n    using var fs = File.OpenRead(path);\n    Span<byte> buf = stackalloc byte[8];\n    fs.Seek(12, SeekOrigin.Begin);\n    while (fs.Read(buf) == 8)\n    {\n        uint sz = BinaryPrimitives.ReadUInt32LittleEndian(buf.Slice(4, 4));\n        if (buf.Slice(0, 4).SequenceEqual(\"anih\"u8)) return true;\n        fs.Seek((long)((sz + 1) & ~1u), SeekOrigin.Current);\n    }\n    return false;\n}","typeGuard":null,"tryCatchPattern":"try\n{\n    using Image<Rgba32> img = Image.Load<Rgba32>(path);\n}\ncatch (InvalidImageContentException)\n{\n    ReportMissingAnih(path);\n}","preventionTips":["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."],"tags":["ani","riff","missing-header","image-decoding"],"backgroundTag":"invalid-image-content","analyzedSha":"59ce6af6fc29027cda277ef62d4d1694a8acce91","analyzedAt":"2026-09-13T18:34:59.331Z","contentChangedAt":"2026-09-13T18:34:59.331Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}