SixLabors/ImageSharp · error · ImageFormatException
ANI bitmap resources require exactly one color plane.
Error message
ANI bitmap resources require exactly one color plane.
What it means
Thrown by AniEncoderCore.Encode when encoding with bitmapResources enabled and the ANI metadata's Planes value is not 0 (unset/default) or 1. ICO/BMP resources embedded in an ANI must declare exactly one color plane, so any other plane count is rejected up front.
Solutions
- Set AniMetadata.Planes to 1 (or 0 to let the encoder default it) before saving as ANI.
- Remove the explicit Planes override so the default is used.
- Encode frames as ICO/CUR resources instead of bitmapResources if multi-plane data is genuinely required.
Example fix
// before metadata.Planes = 2; await image.SaveAsAniAsync(stream, aniOptions); // after metadata.Planes = 1; await image.SaveAsAniAsync(stream, aniOptions);
Defensive patterns
Strategy: validation
Validate before calling
bool planesOk = aniMetadata.Planes is 0 or 1;
if (!planesOk) throw new InvalidOperationException("ANI bitmap resources need Planes = 1."); Try / catch
try { await image.SaveAsAniAsync(stream, options); } catch (ImageFormatException ex) when (ex.Message.Contains("color plane")) { /* fix metadata */ } Prevention
- Leave Planes at its default (0) unless you know you need 1
- Never copy Planes metadata from non-ICO sources into ANI bitmap options
- Validate ANI encoder options with unit tests covering bitmapResources mode
When it happens
Trigger: Calling image.SaveAsAni (or Image.Save with AniEncoder) with bitmapResources configured while AniMetadata.Planes holds a value other than 0 or 1, e.g. 2 or 4.
Common situations: Copying Planes metadata from multi-plane sources, manually setting incorrect plane counts, misunderstanding the ICO one-plane requirement.
Understand the failure class
Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.
Related errors
- ANI bitmap resources require a supported bit depth.
- ANI contains an unsupported embedded frame format.
- ANI cannot mix bitmap resources with ICO or CUR resources.
- ANI bitmap resources cannot contain resolution variants.
- ANI resolution variants must use the same embedded format.
AI-assisted analysis of SixLabors/ImageSharp@59ce6af6fc (2026-09-13).
Data as JSON: /api/errors/888ba7971b00a23f.
Report an issue: GitHub.
Appendix: source
Thrown at src/ImageSharp/Formats/Ani/AniEncoderCore.cs:70
AniMetadata imageMetadata = image.Metadata.GetAniMetadata();
AniFrameMetadata firstMetadata = image.Frames.RootFrame.Metadata.GetAniMetadata();
AniFrameFormat firstFormat = firstMetadata.FrameFormat;
bool bitmapResources = firstFormat is AniFrameFormat.Bmp;
bool writeSequence = imageMetadata.Flags.HasFlag(AniHeaderFlags.ContainsSequence);
uint displayRate = firstMetadata.FrameDelay is 0 ? imageMetadata.DisplayRate : firstMetadata.FrameDelay;
bool hasVariableRates = false;
int groupCount = 0;
int maxGroupSize = 1;
if (bitmapResources && imageMetadata.BitCount is not (0 or 1 or 2 or 4 or 8 or 16 or 24 or 32))
{
throw new ImageFormatException("ANI bitmap resources require a supported bit depth.");
}
if (bitmapResources && imageMetadata.Planes is not (0 or 1))
{
throw new ImageFormatException("ANI bitmap resources require exactly one color plane.");
}
// This validation pass derives the fixed ANI header and largest icon directory without allocating a grouping graph.
// Encoding repeats the linear grouping scan below, trading a cheap pass for zero per-group collections.
for (int frameIndex = 0; frameIndex < image.Frames.Count;)
{
AniFrameMetadata metadata = image.Frames[frameIndex].Metadata.GetAniMetadata();
int groupSize = 1;
if (metadata.FrameFormat is not (AniFrameFormat.Ico or AniFrameFormat.Cur or AniFrameFormat.Bmp))
{
// FrameFormat is public metadata and therefore must be validated before any container bytes are written.
throw new ImageFormatException("ANI contains an unsupported embedded frame format.");
}
// Positive sequence numbers group adjacent resolution variants; non-positive values form independent steps.
if (metadata.SequenceNumber > 0)
{View on GitHub (pinned to 59ce6af6fc)