{"record":{"id":"074cd7d6efd049aa","repo":"dotnet/wpf","slug":"image-onlyonesave","errorCode":null,"errorMessage":"Image_OnlyOneSave","messagePattern":"Image_OnlyOneSave","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/Imaging/BitmapEncoder.cs","lineNumber":327,"sourceCode":"\n        /// <summary>\n        /// Save (encode) the bitmap to the specified stream.\n        /// </summary>\n        /// <param name=\"stream\">Stream to save into</param>\n        public virtual void Save(System.IO.Stream stream)\n        {\n            VerifyAccess();\n            EnsureBuiltIn();\n            EnsureUnmanagedEncoder();\n\n            // No-op to get rid of build error\n            if (_encodeState == EncodeState.None)\n            {\n            }\n\n            if (_hasSaved)\n            {\n                throw new InvalidOperationException(SR.Image_OnlyOneSave);\n            }\n\n            if (_frames == null)\n            {\n                throw new System.NotSupportedException(SR.Format(SR.Image_NoFrames, null));\n            }\n\n            int count = _frames.Count;\n            if (count <= 0)\n            {\n                throw new System.NotSupportedException(SR.Format(SR.Image_NoFrames, null));\n            }\n\n            IntPtr comStream = IntPtr.Zero;\n            SafeMILHandle encoderHandle = _encoderHandle;\n\n            try\n            {","sourceCodeStart":309,"sourceCodeEnd":345,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/Imaging/BitmapEncoder.cs#L309-L345","documentation":"BitmapEncoder.Save enforces that a bitmap container can be encoded exactly once; calling Save a second time on the same encoder throws InvalidOperationException(Image_OnlyOneSave). This is because the WIC encoding stream is consumed by the first save.","triggerScenarios":"Calling encoder.Save() twice on the same BitmapEncoder instance — directly, or indirectly when Save is invoked by GetBitmapImpl, CreateImagePart, CreateBrushImage, ReEncodeImage, or ConvertTo after an explicit Save already ran.","commonSituations":"Saving to a stream and then saving again to a file; defensive re-save in error handling; higher-level APIs (e.g. BitmapSource save paths) invoking Save internally after user code already did; retry loops that re-call Save instead of recreating the encoder.","solutions":["Call Save only once per BitmapEncoder instance","Create a fresh encoder (and reopen the stream) for each save/retry","Track _hasSaved-equivalent state in wrappers before calling Save","Never mix manual encoder.Save with higher-level APIs that call Save internally"],"exampleFix":"// before\nencoder.Save(stream);\nencoder.Save(otherStream); // throws\n// after\nencoder.Save(stream);\nvar encoder2 = new PngBitmapEncoder();\nencoder2.Frames.Add(BitmapFrame.Create(source));\nencoder2.Save(otherStream);","handlingStrategy":"validation","validationCode":"// caller-side: never call Save twice; guard with your own flag\nif (!savedOnce) { encoder.Save(stream); savedOnce = true; }","typeGuard":null,"tryCatchPattern":"try { encoder.Save(stream); }\ncatch (InvalidOperationException ex) when (IsOnlyOneSave(ex)) { log.Error(\"Encoder already saved; create a new encoder instance\"); }","preventionTips":["Treat BitmapEncoder as single-use: one Save per instance","Never retry Save; recreate the encoder and stream instead","Do not combine manual Save with high-level APIs that call Save internally","Reset state (new encoder) in error-recovery paths"],"tags":["wpf","save","invalid-operation","imaging"],"backgroundTag":"invalid-state-transition","analyzedSha":"81131a70a4c573cd62748a5c36908fc4d662daa9","analyzedAt":"2026-09-14T10:12:48.479Z","contentChangedAt":"2026-09-14T10:12:48.479Z","schemaVersion":2},"datasetVersion":"2026-09-22T01:17:13.364Z"}