{"record":{"id":"c910c2e5edf16689","repo":"SixLabors/ImageSharp","slug":"ani-bitmap-resources-require-a-supported-bit-depth","errorCode":null,"errorMessage":"ANI bitmap resources require a supported bit depth.","messagePattern":"ANI bitmap resources require a supported bit depth\\.","errorType":"exception","errorClass":"ImageFormatException","httpStatus":null,"severity":"error","filePath":"src/ImageSharp/Formats/Ani/AniEncoderCore.cs","lineNumber":65,"sourceCode":"    public void Encode<TPixel>(Image<TPixel> image, Stream stream, CancellationToken cancellationToken)\n        where TPixel : unmanaged, IPixel<TPixel>\n    {\n        Guard.NotNull(image, nameof(image));\n        Guard.NotNull(stream, nameof(stream));\n\n        AniMetadata imageMetadata = image.Metadata.GetAniMetadata();\n        AniFrameMetadata firstMetadata = image.Frames.RootFrame.Metadata.GetAniMetadata();\n        AniFrameFormat firstFormat = firstMetadata.FrameFormat;\n        bool bitmapResources = firstFormat is AniFrameFormat.Bmp;\n        bool writeSequence = imageMetadata.Flags.HasFlag(AniHeaderFlags.ContainsSequence);\n        uint displayRate = firstMetadata.FrameDelay is 0 ? imageMetadata.DisplayRate : firstMetadata.FrameDelay;\n        bool hasVariableRates = false;\n        int groupCount = 0;\n        int maxGroupSize = 1;\n\n        if (bitmapResources && imageMetadata.BitCount is not (0 or 1 or 2 or 4 or 8 or 16 or 24 or 32))\n        {\n            throw new ImageFormatException(\"ANI bitmap resources require a supported bit depth.\");\n        }\n\n        if (bitmapResources && imageMetadata.Planes is not (0 or 1))\n        {\n            throw new ImageFormatException(\"ANI bitmap resources require exactly one color plane.\");\n        }\n\n        // This validation pass derives the fixed ANI header and largest icon directory without allocating a grouping graph.\n        // Encoding repeats the linear grouping scan below, trading a cheap pass for zero per-group collections.\n        for (int frameIndex = 0; frameIndex < image.Frames.Count;)\n        {\n            AniFrameMetadata metadata = image.Frames[frameIndex].Metadata.GetAniMetadata();\n            int groupSize = 1;\n\n            if (metadata.FrameFormat is not (AniFrameFormat.Ico or AniFrameFormat.Cur or AniFrameFormat.Bmp))\n            {\n                // FrameFormat is public metadata and therefore must be validated before any container bytes are written.\n                throw new ImageFormatException(\"ANI contains an unsupported embedded frame format.\");","sourceCodeStart":47,"sourceCodeEnd":83,"githubUrl":"https://github.com/SixLabors/ImageSharp/blob/59ce6af6fc29027cda277ef62d4d1694a8acce91/src/ImageSharp/Formats/Ani/AniEncoderCore.cs#L47-L83","documentation":"Thrown by AniEncoderCore.Encode when encoding with bitmapResources enabled and the ANI metadata's BitCount is not one of the ICO/BMP-supported depths (0 meaning unset/default, 1, 2, 4, 8, 16, 24, 32). Bitmap frame resources inside an ANI require a valid bit depth to be written into the icon directory entries.","triggerScenarios":"Calling image.SaveAsAni (or Image.Save with AniEncoder) with bitmapResources configured while AniMetadata.BitCount holds an unsupported value such as 3, 5, or 64.","commonSituations":"Configuring ANI encoding options with a bit depth copied from a non-ICO source, typo'd metadata values, round-tripping metadata from exotic formats into ANI bitmap mode.","solutions":["Set the ANI metadata BitCount to 0 (default) or one of 1, 2, 4, 8, 16, 24, 32 before encoding.","If the source depth is unsupported, encode frames as ICO/CUR resources instead of bitmapResources, or convert the images.","Validate the BitCount value against the supported set before calling Save."],"exampleFix":"// before\nmetadata.BitCount = 3;\nawait image.SaveAsAniAsync(stream, aniOptions);\n// after\nmetadata.BitCount = 32; // supported: 0,1,2,4,8,16,24,32\nawait image.SaveAsAniAsync(stream, aniOptions);","handlingStrategy":"validation","validationCode":"static readonly int[] SupportedBitDepths = { 0, 1, 2, 4, 8, 16, 24, 32 };\nbool bitDepthOk = SupportedBitDepths.Contains(aniMetadata.BitCount);","typeGuard":null,"tryCatchPattern":"try { await image.SaveAsAniAsync(stream, options); } catch (ImageFormatException ex) when (ex.Message.Contains(\"bit depth\")) { /* fix metadata */ }","preventionTips":["Only set BitCount to 0, 1, 2, 4, 8, 16, 24, or 32 when using bitmapResources","Centralize ANI metadata construction in one validated helper","Round-trip test encoded ANI files in CI"],"tags":["image-encoding","ani","bit-depth","configuration","validation"],"backgroundTag":"invalid-config-value","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"}