SixLabors/ImageSharp · error · ImageFormatException

ANI resolution variants must use the same frame delay.

Error message

ANI resolution variants must use the same frame delay.

What it means

Frames grouped as resolution variants of one resource share a single animation step and therefore a single rate value. The encoder requires every frame in a group to declare the identical AniFrameMetadata.FrameDelay; a differing delay would be unrepresentable in the ANI rate table, so it throws ImageFormatException.

Solutions

  1. Assign the same FrameDelay to all frames sharing a SequenceNumber.
  2. Set FrameDelay = 0 on variant frames so the group falls back to the shared display rate.
  3. Split variants with different timing into separate animation steps (distinct SequenceNumbers).

Example fix

// before
f0.Metadata.GetAniMetadata().FrameDelay = 100;
f1.Metadata.GetAniMetadata().FrameDelay = 200; // same variant group
// after
f0.Metadata.GetAniMetadata().FrameDelay = 100;
f1.Metadata.GetAniMetadata().FrameDelay = 100;
Defensive patterns

Strategy: validation

Validate before calling

var delays = image.Frames
    .Where(f => f.Metadata.GetAniMetadata().SequenceNumber == targetSeq)
    .Select(f => f.Metadata.GetAniMetadata().FrameDelay).Distinct().ToList();
if (delays.Count > 1) throw new InvalidOperationException("Variant group delays differ.");

Try / catch

try { image.SaveAsAni(stream); }
catch (ImageFormatException ex) { Log(ex.Message); }

Prevention

When it happens

Trigger: Encoding an ANI where consecutive frames with the same positive SequenceNumber (one variant group) have differing FrameDelay values.

Common situations: Varying per-frame timing across resolution variants of the same cursor image; delays copied from per-frame sources (e.g. GIF) without normalization before ANI encoding.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


AI-assisted analysis of SixLabors/ImageSharp@59ce6af6fc (2026-09-13). Data as JSON: /api/errors/975012ed373e8814. Report an issue: GitHub.

Appendix: source

Thrown at src/ImageSharp/Formats/Ani/AniEncoderCore.cs:118

            if (bitmapResources && groupSize > 1)
            {
                // Only ICO/CUR directories can contain multiple resolution variants in one physical resource.
                throw new ImageFormatException("ANI bitmap resources cannot contain resolution variants.");
            }

            // All variants share one animation step, which requires one child format and one rate value.
            for (int i = 1; i < groupSize; i++)
            {
                AniFrameMetadata current = image.Frames[frameIndex + i].Metadata.GetAniMetadata();
                if (current.FrameFormat != metadata.FrameFormat)
                {
                    throw new ImageFormatException("ANI resolution variants must use the same embedded format.");
                }

                if (current.FrameDelay != metadata.FrameDelay)
                {
                    throw new ImageFormatException("ANI resolution variants must use the same frame delay.");
                }
            }

            uint frameDelay = metadata.FrameDelay is 0 ? displayRate : metadata.FrameDelay;
            hasVariableRates |= frameDelay != displayRate;
            maxGroupSize = Math.Max(maxGroupSize, groupSize);
            groupCount++;
            frameIndex += groupSize;
        }

        // Icon-based ANI files leave global geometry and pixel layout at zero because each ICO/CUR entry owns those values.
        AniHeader header = new()
        {
            BytesInHeader = AniHeader.Size,
            FrameCount = (uint)groupCount,
            StepCount = (uint)groupCount,
            Width = bitmapResources ? imageMetadata.Width is 0 ? (uint)image.Width : imageMetadata.Width : 0,
            Height = bitmapResources ? imageMetadata.Height is 0 ? (uint)image.Height : imageMetadata.Height : 0,

View on GitHub (pinned to 59ce6af6fc)