{"record":{"id":"44e670b675c7b3c2","repo":"SixLabors/ImageSharp","slug":"the-ani-sequence-references-a-missing-frame-resource","errorCode":null,"errorMessage":"The ANI sequence references a missing frame resource.","messagePattern":"The ANI sequence references a missing frame resource\\.","errorType":"exception","errorClass":"InvalidImageContentException","httpStatus":null,"severity":"warning","filePath":"src/ImageSharp/Formats/Ani/AniDecoderCore.cs","lineNumber":96,"sourceCode":"\n            // Keep the owners alive and resolve their spans once; sequence and rate lookup occurs for every animation step.\n            IMemoryOwner<uint>? sequenceOwner = this.sequence;\n            bool hasSequence = sequenceOwner is not null;\n            ReadOnlySpan<uint> sequence = sequenceOwner is null ? [] : sequenceOwner.GetSpan();\n            ReadOnlySpan<uint> rates = this.rates is null ? [] : this.rates.GetSpan();\n            int stepCount = hasSequence ? sequence.Length : resources.Count;\n            int maxFrames = (int)this.Options.MaxFrames;\n            outputFrames.EnsureCapacity(Math.Min(maxFrames, resources.Count));\n\n            for (int step = 0; step < stepCount && outputFrames.Count < maxFrames; step++)\n            {\n                cancellationToken.ThrowIfCancellationRequested();\n\n                uint resourceIndex = hasSequence ? sequence[step] : (uint)step;\n                if (resourceIndex >= resources.Count || resources[(int)resourceIndex] is not { } resource)\n                {\n                    // A bad ordering entry is recoverable ancillary data: the remaining valid steps can still be decoded.\n                    this.ExecuteAncillarySegmentAction(() => throw new InvalidImageContentException(\"The ANI sequence references a missing frame resource.\"));\n\n                    continue;\n                }\n\n                (AniFrameFormat format, Image<TPixel> resourceImage) = resource;\n                uint frameDelay = step < rates.Length ? rates[step] : this.aniMetadata.DisplayRate;\n\n                for (int i = 0; i < resourceImage.Frames.Count && outputFrames.Count < maxFrames; i++)\n                {\n                    ImageFrame<TPixel> source = resourceImage.Frames[i];\n                    ImageFrame<TPixel> target = new(this.Options.Configuration, this.Dimensions);\n\n                    // ANI flattens differently sized ICO/CUR variants into one ImageSharp frame collection.\n                    // The common canvas preserves that invariant, while encoding dimensions retain the source size.\n                    for (int y = 0; y < source.Height; y++)\n                    {\n                        source.PixelBuffer.DangerousGetRowSpan(y).CopyTo(target.PixelBuffer.DangerousGetRowSpan(y));\n                    }","sourceCodeStart":78,"sourceCodeEnd":114,"githubUrl":"https://github.com/SixLabors/ImageSharp/blob/59ce6af6fc29027cda277ef62d4d1694a8acce91/src/ImageSharp/Formats/Ani/AniDecoderCore.cs#L78-L114","documentation":"During ANI decoding, each animation step is mapped to a frame resource either via the 'anih'-companion sequence ('seq ') chunk or, when absent, by positional index. This error is raised when a step's resource index is out of range or points to a slot that failed to decode. Because the sequence chunk is treated as ancillary (recoverable) metadata, the error is reported without aborting the whole decode, and any remaining valid steps are still decoded.","triggerScenarios":"Calling Image.DecodeAsync (ANI decoder) on a file whose 'seq ' chunk contains an index >= the number of parsed frame resources, or whose positional step count exceeds decodable resources (e.g. an 'icon'/'fram' chunk failed to parse, leaving a null resource slot).","commonSituations":"Hand-edited or tool-corrupted ANI/cursor files where the seq chunk was not regenerated after icons were removed; ANI files whose embedded icon chunks are malformed and silently dropped by the parser, shifting index alignment.","solutions":["Regenerate or fix the ANI file so every 'seq ' entry is a valid index into the existing icon/frame resources (0-based, < resource count).","Verify all embedded icon frames in the 'fram'/'icon' chunks decode correctly; re-encode frames with a known-good tool.","If you only need the decodable frames, treat this as a warning: the decode succeeds with the remaining steps, but the animation will skip steps."],"exampleFix":"// before: seq chunk referencing 5 resources\nuint[] sequence = { 0, 1, 2, 3, 7 }; // 7 out of range\n// after: indices clamped to valid resources\nuint[] sequence = { 0, 1, 2, 3, 4 };","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try\n{\n    using Image<Rgba32> img = Image.Load<Rgba32>(aniPath);\n}\ncatch (InvalidImageContentException ex)\n{\n    // Recoverable: decode continues for valid steps; log and accept partial animation.\n    logger.LogWarning(ex, \"ANI sequence references missing frames; partial decode accepted.\");\n}","preventionTips":["Regenerate the 'seq ' chunk whenever frames are added or removed from an ANI.","Validate seq indices (0-based, < frame count) when building ANI files programmatically.","Prefer authoring tools that emit sequence metadata automatically."],"tags":["ani","image-decoding","corrupt-file","sequence"],"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"}