SixLabors/ImageSharp · critical · InvalidImageContentException
The ANI file does not contain any decodable animation steps.
Error message
The ANI file does not contain any decodable animation steps.
What it means
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.
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.
Example fix
// before
using Image<Rgba32> img = Image.Load<Rgba32>(path); // throws
// after
if (!HasAniFrames(path)) { fallbackToStaticCursor(); }
using Image<Rgba32> img = Image.Load<Rgba32>(path); Defensive patterns
Strategy: try-catch
Validate before calling
// Quick pre-check: file exists and is at least large enough for a RIFF header + anih + one icon bool plausiblyDecodable = File.Exists(path) && new FileInfo(path).Length > 64;
Try / catch
try
{
using Image<Rgba32> img = Image.Load<Rgba32>(aniPath);
}
catch (InvalidImageContentException)
{
ShowStaticPlaceholderCursor(); // no decodable frames at all
} Prevention
- 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.
When it happens
Trigger: 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).
Common situations: 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.
Related errors
- The ANI sequence references a missing frame resource.
- The ANI file does not contain any identifiable animation…
- The ANI RIFF container size is invalid.
- The stream does not contain an ANI RIFF container.
- The ANI file does not contain an animation header.
AI-assisted analysis of SixLabors/ImageSharp@59ce6af6fc (2026-09-13).
Data as JSON: /api/errors/b2ea1a1bc4b1eb4f.
Report an issue: GitHub.
Appendix: source
Thrown at src/ImageSharp/Formats/Ani/AniDecoderCore.cs:124
ImageFrame<TPixel> source = resourceImage.Frames[i];
ImageFrame<TPixel> target = new(this.Options.Configuration, this.Dimensions);
// ANI flattens differently sized ICO/CUR variants into one ImageSharp frame collection.
// The common canvas preserves that invariant, while encoding dimensions retain the source size.
for (int y = 0; y < source.Height; y++)
{
source.PixelBuffer.DangerousGetRowSpan(y).CopyTo(target.PixelBuffer.DangerousGetRowSpan(y));
}
AniFrameMetadata metadata = CreateFrameMetadata(source.Metadata, format, step + 1, frameDelay, source.Size);
target.Metadata.SetFormatMetadata(AniFormat.Instance, metadata);
outputFrames.Add(target);
}
}
if (outputFrames.Count is 0)
{
throw new InvalidImageContentException("The ANI file does not contain any decodable animation steps.");
}
// Image takes ownership of the supplied frames; only the temporary decoded resources remain locally owned.
Image<TPixel> image = new(this.Options.Configuration, this.imageMetadata, outputFrames);
outputFramesOwned = true;
return image;
}
finally
{
// Embedded images are temporary resource containers; their pixels have already been copied to the flattened output frames.
foreach ((AniFrameFormat Format, Image<TPixel> Image)? resource in resources)
{
if (resource is { } value)
{
value.Image.Dispose();
}
}View on GitHub (pinned to 59ce6af6fc)