{"record":{"id":"3f7fd01242fa07bd","repo":"SixLabors/ImageSharp","slug":"an-error-occurred-when-processing-the-image-using-this","errorCode":null,"errorMessage":"An error occurred when processing the image using {this.GetType().Name}. The processor changed the number of frames.","messagePattern":"An error occurred when processing the image using (.+?)\\. The processor changed the number of frames\\.","errorType":"exception","errorClass":"ImageProcessingException","httpStatus":null,"severity":"error","filePath":"src/ImageSharp/Processing/Processors/CloningImageProcessor{TPixel}.cs","lineNumber":177,"sourceCode":"        ImageFrame<TPixel>[] destinationFrames = new ImageFrame<TPixel>[source.Frames.Count];\n        for (int i = 0; i < destinationFrames.Length; i++)\n        {\n            destinationFrames[i] = new ImageFrame<TPixel>(\n                this.Configuration,\n                destinationSize.Width,\n                destinationSize.Height,\n                source.Frames[i].Metadata.DeepClone());\n        }\n\n        // Use the overload to prevent an extra frame being added.\n        return new Image<TPixel>(this.Configuration, source.Metadata.DeepClone(), destinationFrames);\n    }\n\n    private void CheckFrameCount(Image<TPixel> a, Image<TPixel> b)\n    {\n        if (a.Frames.Count != b.Frames.Count)\n        {\n            throw new ImageProcessingException($\"An error occurred when processing the image using {this.GetType().Name}. The processor changed the number of frames.\");\n        }\n    }\n}\n","sourceCodeStart":159,"sourceCodeEnd":181,"githubUrl":"https://github.com/SixLabors/ImageSharp/blob/59ce6af6fc29027cda277ef62d4d1694a8acce91/src/ImageSharp/Processing/Processors/CloningImageProcessor{TPixel}.cs#L159-L181","documentation":"CloningImageProcessor verifies that cloning operations never add or remove frames: after cloning the source into the destination it compares frame counts. A mismatch throws ImageProcessingException, indicating the processor implementation itself corrupted the frame structure — a library-internal invariant rather than user input error.","triggerScenarios":"A custom ICloningImageProcessor whose ApplyImageFrames/ApplyFrame logic or BeforeImageApply/AfterImageApply mutates the destination's frame collection; calling Execute/CloneAndExecute on an image whose frames changed concurrently during processing.","commonSituations":"Writing a custom clone processor that calls Frames.Add/Remove or CreateFrame inside the processing pipeline; buggy custom processor implementations after an ImageSharp version upgrade changed the cloning contract.","solutions":["Do not add or remove frames inside a cloning processor; operate only on existing frame pixels","Perform frame-count changes on the Image<TPixel> before/after the processor runs, using a non-cloning flow","Update custom processors to the current ICloningImageProcessor contract after upgrading ImageSharp","Catch ImageProcessingException around custom processor execution to detect broken implementations"],"exampleFix":"// before\nprotected override void AfterImageApply(Image<TPixel> destination) => destination.Frames.RemoveFrame(0);\n// after\nprotected override void AfterImageApply(Image<TPixel> destination) { /* leave frame count intact */ }","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try { image.Mutate(ctx => ctx.ApplyProcessor(customCloningProcessor)); } catch (ImageProcessingException ex) when (ex.Message.Contains(\"number of frames\")) { log.Error(ex, \"Processor mutated frame count\"); throw; }","preventionTips":["Never add/remove/create frames inside a cloning processor","Change frame structure on the Image outside processing","Re-test custom processors after ImageSharp upgrades"],"tags":["processing","frames","internal-invariant"],"backgroundTag":"internal-invariant-violation","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"}