dotnet/wpf · error · InvalidOperationException
Image_OnlyOneSave
Error message
Image_OnlyOneSave
What it means
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.
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
Example fix
// before encoder.Save(stream); encoder.Save(otherStream); // throws // after encoder.Save(stream); var encoder2 = new PngBitmapEncoder(); encoder2.Frames.Add(BitmapFrame.Create(source)); encoder2.Save(otherStream);
Defensive patterns
Strategy: validation
Validate before calling
// caller-side: never call Save twice; guard with your own flag
if (!savedOnce) { encoder.Save(stream); savedOnce = true; } Try / catch
try { encoder.Save(stream); }
catch (InvalidOperationException ex) when (IsOnlyOneSave(ex)) { log.Error("Encoder already saved; create a new encoder instance"); } Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- Image_EncoderNoColorContext
- Image_EncoderNoGlobalMetadata
- Image_EncoderNoGlobalThumbnail
- Image_EncoderNoPreview
- Image_NoFrames
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/074cd7d6efd049aa.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/Imaging/BitmapEncoder.cs:327
/// <summary>
/// Save (encode) the bitmap to the specified stream.
/// </summary>
/// <param name="stream">Stream to save into</param>
public virtual void Save(System.IO.Stream stream)
{
VerifyAccess();
EnsureBuiltIn();
EnsureUnmanagedEncoder();
// No-op to get rid of build error
if (_encodeState == EncodeState.None)
{
}
if (_hasSaved)
{
throw new InvalidOperationException(SR.Image_OnlyOneSave);
}
if (_frames == null)
{
throw new System.NotSupportedException(SR.Format(SR.Image_NoFrames, null));
}
int count = _frames.Count;
if (count <= 0)
{
throw new System.NotSupportedException(SR.Format(SR.Image_NoFrames, null));
}
IntPtr comStream = IntPtr.Zero;
SafeMILHandle encoderHandle = _encoderHandle;
try
{View on GitHub (pinned to 81131a70a4)