{"record":{"id":"76778151d88be36e","repo":"SixLabors/ImageSharp","slug":"ani-resolution-variants-must-use-the-same-embedded-format","errorCode":null,"errorMessage":"ANI resolution variants must use the same embedded format.","messagePattern":"ANI resolution variants must use the same embedded format\\.","errorType":"exception","errorClass":"ImageFormatException","httpStatus":null,"severity":"error","filePath":"src/ImageSharp/Formats/Ani/AniEncoderCore.cs","lineNumber":113,"sourceCode":"            if (bitmapResources != (metadata.FrameFormat is AniFrameFormat.Bmp))\n            {\n                // AF_ICON applies to the complete file, so raw DIB resources cannot coexist with ICO/CUR resources.\n                throw new ImageFormatException(\"ANI cannot mix bitmap resources with ICO or CUR resources.\");\n            }\n\n            if (bitmapResources && groupSize > 1)\n            {\n                // Only ICO/CUR directories can contain multiple resolution variants in one physical resource.\n                throw new ImageFormatException(\"ANI bitmap resources cannot contain resolution variants.\");\n            }\n\n            // All variants share one animation step, which requires one child format and one rate value.\n            for (int i = 1; i < groupSize; i++)\n            {\n                AniFrameMetadata current = image.Frames[frameIndex + i].Metadata.GetAniMetadata();\n                if (current.FrameFormat != metadata.FrameFormat)\n                {\n                    throw new ImageFormatException(\"ANI resolution variants must use the same embedded format.\");\n                }\n\n                if (current.FrameDelay != metadata.FrameDelay)\n                {\n                    throw new ImageFormatException(\"ANI resolution variants must use the same frame delay.\");\n                }\n            }\n\n            uint frameDelay = metadata.FrameDelay is 0 ? displayRate : metadata.FrameDelay;\n            hasVariableRates |= frameDelay != displayRate;\n            maxGroupSize = Math.Max(maxGroupSize, groupSize);\n            groupCount++;\n            frameIndex += groupSize;\n        }\n\n        // Icon-based ANI files leave global geometry and pixel layout at zero because each ICO/CUR entry owns those values.\n        AniHeader header = new()\n        {","sourceCodeStart":95,"sourceCodeEnd":131,"githubUrl":"https://github.com/SixLabors/ImageSharp/blob/59ce6af6fc29027cda277ef62d4d1694a8acce91/src/ImageSharp/Formats/Ani/AniEncoderCore.cs#L95-L131","documentation":"All frames in one resolution-variant group (same positive SequenceNumber) become variants of a single embedded resource, which must have one child format. If a later frame in the group declares a different AniFrameMetadata.FrameFormat than the group's first frame, the encoder throws ImageFormatException.","triggerScenarios":"Encoding an ANI where frames sharing a SequenceNumber have differing FrameFormat values (e.g. first frame Ico, subsequent frame Cur or Bmp).","commonSituations":"Merging frames from different decoded cursors/icons into one variant group; copy-paste metadata edits changing only some frames' format.","solutions":["Set the same FrameFormat on every frame that shares a SequenceNumber.","Give each differently-formatted frame its own SequenceNumber so it is treated as an independent step.","Normalize metadata right before encoding with a loop over image.Frames."],"exampleFix":"// before\nf0.Metadata.GetAniMetadata().FrameFormat = AniFrameFormat.Ico;\nf1.Metadata.GetAniMetadata().FrameFormat = AniFrameFormat.Cur; // same group\n// after\nf0.Metadata.GetAniMetadata().FrameFormat = AniFrameFormat.Ico;\nf1.Metadata.GetAniMetadata().FrameFormat = AniFrameFormat.Ico;","handlingStrategy":"validation","validationCode":"var groups = image.Frames.Select((f,i) => (f.Metadata.GetAniMetadata(), i))\n    .GroupBy(x => x.Item1.SequenceNumber).Where(g => g.Key > 0);\nforeach (var g in groups)\n    if (g.Select(x => x.Item1.FrameFormat).Distinct().Count() > 1)\n        throw new InvalidOperationException(\"Variant group formats differ.\");","typeGuard":null,"tryCatchPattern":"try { image.SaveAsAni(stream); }\ncatch (ImageFormatException ex) { Log(ex.Message); }","preventionTips":["Normalize FrameFormat per SequenceNumber group before encoding.","Assign distinct SequenceNumbers to frames with different formats.","Re-verify metadata after merging frames from multiple sources."],"tags":["image-encoding","ani","metadata-validation"],"backgroundTag":"schema-validation-failed","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"}