{"record":{"id":"b2ea1a1bc4b1eb4f","repo":"SixLabors/ImageSharp","slug":"the-ani-file-does-not-contain-any-decodable-animation-steps","errorCode":null,"errorMessage":"The ANI file does not contain any decodable animation steps.","messagePattern":"The ANI file does not contain any decodable animation steps\\.","errorType":"exception","errorClass":"InvalidImageContentException","httpStatus":null,"severity":"critical","filePath":"src/ImageSharp/Formats/Ani/AniDecoderCore.cs","lineNumber":124,"sourceCode":"                    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                    }\n\n                    AniFrameMetadata metadata = CreateFrameMetadata(source.Metadata, format, step + 1, frameDelay, source.Size);\n                    target.Metadata.SetFormatMetadata(AniFormat.Instance, metadata);\n                    outputFrames.Add(target);\n                }\n            }\n\n            if (outputFrames.Count is 0)\n            {\n                throw new InvalidImageContentException(\"The ANI file does not contain any decodable animation steps.\");\n            }\n\n            // Image takes ownership of the supplied frames; only the temporary decoded resources remain locally owned.\n            Image<TPixel> image = new(this.Options.Configuration, this.imageMetadata, outputFrames);\n            outputFramesOwned = true;\n\n            return image;\n        }\n        finally\n        {\n            // Embedded images are temporary resource containers; their pixels have already been copied to the flattened output frames.\n            foreach ((AniFrameFormat Format, Image<TPixel> Image)? resource in resources)\n            {\n                if (resource is { } value)\n                {\n                    value.Image.Dispose();\n                }\n            }","sourceCodeStart":106,"sourceCodeEnd":142,"githubUrl":"https://github.com/SixLabors/ImageSharp/blob/59ce6af6fc29027cda277ef62d4d1694a8acce91/src/ImageSharp/Formats/Ani/AniDecoderCore.cs#L106-L142","documentation":"After decoding all animation steps, the ANI decoder checks whether any output frames were produced. If every step failed to map to a decodable resource (or there were no steps), there is no image to return, so an InvalidImageContentException is thrown. This is the terminal failure of the decode path after per-step recoverable errors have already been tolerated.","triggerScenarios":"Calling Image.DecodeAsync<TPixel> on an ANI stream where zero steps produced frames: an empty or entirely-invalid 'seq ' chunk, all frame resources failing to decode, or an ANI file with no 'fram'/'icon' chunks at all (which usually fails earlier with the no-resources error).","commonSituations":"Zero-byte or truncated ANI downloads; cursor packs where icon data was stripped but container metadata kept; passing a non-ANI stream misdetected as ANI.","solutions":["Inspect the ANI file with a RIFF viewer: confirm it contains at least one 'fram' chunk holding a decodable icon.","Re-export the animation/cursor with a reliable tool (e.g. IcoFX, GIMP cursor plugins) so frame data is present.","Re-download or restore the file from a known-good source if it is truncated or corrupted in transit."],"exampleFix":"// before\nusing Image<Rgba32> img = Image.Load<Rgba32>(path); // throws\n// after\nif (!HasAniFrames(path)) { fallbackToStaticCursor(); }\nusing Image<Rgba32> img = Image.Load<Rgba32>(path);","handlingStrategy":"try-catch","validationCode":"// Quick pre-check: file exists and is at least large enough for a RIFF header + anih + one icon\nbool plausiblyDecodable = File.Exists(path) && new FileInfo(path).Length > 64;","typeGuard":null,"tryCatchPattern":"try\n{\n    using Image<Rgba32> img = Image.Load<Rgba32>(aniPath);\n}\ncatch (InvalidImageContentException)\n{\n    ShowStaticPlaceholderCursor(); // no decodable frames at all\n}","preventionTips":["Verify ANI files contain at least one 'fram'/'icon' chunk before shipping them.","Re-download files whose size differs from the source.","Keep a fallback static cursor for animations that fail to decode."],"tags":["ani","image-decoding","empty-input","corrupt-file"],"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"}