{"record":{"id":"712363db5b026e76","repo":"SixLabors/ImageSharp","slug":"ico-and-cur-resources-cannot-contain-more-than-65535","errorCode":null,"errorMessage":"ICO and CUR resources cannot contain more than 65535 directory entries.","messagePattern":"ICO and CUR resources cannot contain more than 65535 directory entries\\.","errorType":"exception","errorClass":"ImageFormatException","httpStatus":null,"severity":"error","filePath":"src/ImageSharp/Formats/Icon/IconEncoderCore.cs","lineNumber":86,"sourceCode":"\n    /// <summary>\n    /// Encodes a contiguous source-frame range using a stack-only metadata provider.\n    /// </summary>\n    /// <typeparam name=\"TPixel\">The source pixel type.</typeparam>\n    /// <typeparam name=\"TProvider\">The metadata provider type.</typeparam>\n    /// <param name=\"image\">The source image.</param>\n    /// <param name=\"stream\">The destination stream.</param>\n    /// <param name=\"frameIndex\">The first source-frame index.</param>\n    /// <param name=\"entries\">The directory metadata for the source frames.</param>\n    /// <param name=\"provider\">The frame metadata provider.</param>\n    /// <param name=\"cancellationToken\">The token to monitor for cancellation requests.</param>\n    internal void Encode<TPixel, TProvider>(Image<TPixel> image, Stream stream, int frameIndex, Span<EncodingFrameMetadata> entries, TProvider provider, CancellationToken cancellationToken)\n        where TPixel : unmanaged, IPixel<TPixel>\n        where TProvider : struct, IEncodingFrameMetadataProvider\n    {\n        if ((uint)entries.Length > ushort.MaxValue)\n        {\n            throw new ImageFormatException(\"ICO and CUR resources cannot contain more than 65535 directory entries.\");\n        }\n\n        // Offsets stored in ICO/CUR entries are relative to the start of this child resource, not the containing ANI stream.\n        long basePosition = stream.Position;\n        IconDir fileHeader = new(this.iconFileType, (ushort)entries.Length);\n\n        // Reserve the directory first because BytesInRes and ImageOffset are known only after each payload is encoded.\n        int dataOffset = IconDir.Size + (IconDirEntry.Size * entries.Length);\n        _ = stream.Seek(dataOffset, SeekOrigin.Current);\n\n        for (int i = 0; i < entries.Length; i++)\n        {\n            cancellationToken.ThrowIfCancellationRequested();\n\n            // Since Windows Vista, the size of an image is determined from the BITMAPINFOHEADER structure or PNG image data\n            // which technically allows storing icons with larger than 256 pixels, but such larger sizes are not recommended by Microsoft.\n            ImageFrame<TPixel> frame = image.Frames[frameIndex + i];\n","sourceCodeStart":68,"sourceCodeEnd":104,"githubUrl":"https://github.com/SixLabors/ImageSharp/blob/59ce6af6fc29027cda277ef62d4d1694a8acce91/src/ImageSharp/Formats/Icon/IconEncoderCore.cs#L68-L104","documentation":"Thrown during icon encoding when more than ushort.MaxValue (65535) directory entries are supplied. The ICO/CUR ICONDIR stores Count as a 16-bit value, so SixLabors.ImageSharp cannot represent more entries and throws ImageFormatException before writing anything.","triggerScenarios":"Calling the icon encoder (Save as ICO/CUR, Image.Save with IcoEncoder) with an image collection or metadata provider yielding more than 65535 frames/entries — practically only via programmatic batch encoding.","commonSituations":"Programmatic icon generation loops that accidentally encode thousands of frames; using the ICO encoder on a large animated image's frames instead of a real multi-format-capable encoder; off-by-scale bugs in entry collection.","solutions":["Reduce the number of encoded frames to 65535 or fewer (typically icons have 1–20 entries)","Validate entries.Length before encoding and split or truncate the set","Use a different container format if you genuinely need many frames","Catch ImageFormatException and report the limit to the user"],"exampleFix":"// before\nusing var imageCollection = Image.LoadFrames(source); // could exceed 65535\nimageCollection.Save(\"out.ico\");\n// after\nusing var imageCollection = Image.LoadFrames(source);\nif (imageCollection.Frames.Count > 65535)\n    throw new InvalidOperationException(\"ICO supports at most 65535 entries\");\nimageCollection.Save(\"out.ico\");","handlingStrategy":"validation","validationCode":"// before saving, enforce the ICONDIR 16-bit entry limit\nif ((uint)frames.Count > ushort.MaxValue)\n    throw new InvalidOperationException($\"ICO supports at most {ushort.MaxValue} entries, got {frames.Count}\");","typeGuard":null,"tryCatchPattern":"try\n{\n    image.Save(stream, new IcoEncoder());\n}\ncatch (ImageFormatException ex)\n{\n    // >65535 entries requested\n    throw new InvalidOperationException(\"Too many frames for ICO\", ex);\n}","preventionTips":["Limit icon entries to a sane number (typically < 20 sizes)","Count frames before encoding and split if necessary","Never reuse the ICO encoder for large frame collections"],"tags":["icon","ico","encoder","limit-exceeded"],"backgroundTag":"value-out-of-range","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"}