dotnet/wpf · error · InvalidOperationException
SR.Image_MetadataReadOnly
Error message
SR.Image_MetadataReadOnly
What it means
Thrown from BitmapMetadata.SetQuery (and similar write paths) when the metadata object was opened in read-only mode (_readOnly == true). WPF marks metadata read-only when it comes from a read-only source, such as a BitmapFrame decoded from a stream not opened for writing or metadata obtained from a frozen frame. Writing a query to such metadata is an invalid operation, so the library refuses it up front.
Solutions
- Obtain a writable BitmapMetadata: decode with write access (e.g., create metadata via new BitmapMetadata("jpeg") and set it on the encoder) rather than mutating decoder-supplied metadata.
- Check IsReadOnly (or IsFrozen) before calling SetQuery and clone the metadata into a new writable BitmapMetadata if needed.
- Use BitmapEncoder with InPlaceBitmapMetadataWriter for in-place edits on file streams opened for writing.
- Wrap SetQuery in try/catch for InvalidOperationException and surface that the metadata source is read-only.
Example fix
// before
var meta = frame.Metadata as BitmapMetadata;
meta.SetQuery("/app1/ifd/exif/{ushort=271}", "Canon"); // throws: read-only
// after
var meta = new BitmapMetadata("jpeg");
meta.SetQuery("/app1/ifd/exif/{ushort=271}", "Canon");
encoder.Frames.Add(BitmapFrame.Create(source, frame.Thumbnail, meta, frame.ColorContexts)); Defensive patterns
Strategy: validation
Validate before calling
if (meta == null) throw new ArgumentNullException(nameof(meta));
if (meta.IsReadOnly || meta.IsFrozen)
meta = new BitmapMetadata("jpeg") { /* copy fields */ }; Type guard
static bool IsWritable(BitmapMetadata meta) => meta != null && !meta.IsReadOnly && !meta.IsFrozen;
Try / catch
try { meta.SetQuery(query, value); }
catch (InvalidOperationException) { meta = CloneWritable(meta); meta.SetQuery(query, value); } Prevention
- Check IsReadOnly before every SetQuery call.
- Treat decoder-supplied metadata as read-only; create a new BitmapMetadata for encoder output.
- Use InPlaceBitmapMetadataWriter for file edits instead of mutating decoded metadata.
- Don't share one BitmapMetadata between a read-only frame and an encoder.
When it happens
Trigger: Calling BitmapMetadata.SetQuery(query, value) on a BitmapMetadata whose _readOnly flag is set — typically metadata retrieved from a frame of an image decoded without write access (e.g., BitmapCreateOptions or reading from a non-writable stream), or metadata from a frozen bitmap.
Common situations: Trying to embed EXIF/IPTC/XMP tags into a JPEG loaded from a web stream or Resource; reading metadata with a decoder and then attempting SetQuery on it; sharing one BitmapMetadata between a read-only frame and an intended-write encoder.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- SR.Image_MetadataInitializationIncomplete
- 0x80040209
- Cannot remove signature from read-only file.
- Cannot sign read-only file.
- CollectionIsFixedSize
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/d51ce05eacc4e8b6.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/Imaging/BitmapMetadata.cs:1018
#endregion
#region Query Methods
/// <summary>
///
/// </summary>
public void SetQuery(String query, object value)
{
WritePreamble();
ArgumentNullException.ThrowIfNull(query);
ArgumentNullException.ThrowIfNull(value);
if (_readOnly)
{
throw new System.InvalidOperationException(SR.Image_MetadataReadOnly);
}
// Store these for debugging stress failures.
_setQueryString = query;
_setQueryValue = value;
EnsureBitmapMetadata();
PROPVARIANT propVar = new PROPVARIANT();
try
{
propVar.Init(value);
if (propVar.RequiresSyncObject)
{
BitmapMetadata metadata = value as BitmapMetadata;
Invariant.Assert(metadata != null);View on GitHub (pinned to 81131a70a4)