dotnet/wpf · error · NotSupportedException
Cannot change content of read-only stream.
Error message
Cannot change content of read-only stream.
What it means
UnsafeIndexingFilterStream represents the read-only content stream handed out by a COM indexing filter. SetLength is intentionally unsupported — no indexing filter requires resizing its content — so after a disposed check the method unconditionally throws NotSupportedException(SR.StreamDoesNotSupportWrite), whose text is "Cannot change content of read-only stream."
Solutions
- Do not call SetLength on this stream; it is read-only by contract.
- Check stream.CanWrite / this stream type before resizing and copy to a writable MemoryStream if mutation is needed.
- If content must be modified, open the package part with PackagePart.GetStream(FileMode.Create, FileAccess.Write) instead of using the filter stream.
Example fix
// before
stream.SetLength(0);
stream.Write(data, 0, data.Length);
// after
if (!stream.CanWrite)
{
var writable = new MemoryStream();
stream.CopyTo(writable);
stream = writable; // mutate the copy instead
} Defensive patterns
Strategy: validation
Validate before calling
if (stream is UnsafeIndexingFilterStream || !stream.CanWrite)
throw new InvalidOperationException("Stream is read-only; SetLength not allowed"); Type guard
static bool IsWritable(Stream s) => s != null && s.CanWrite && !(s is System.IO.Packaging.UnsafeIndexingFilterStream);
Try / catch
try { stream.SetLength(newLength); }
catch (NotSupportedException ex) when (ex.Message.Contains("read-only"))
{
// copy to a writable stream and resize there
} Prevention
- Check CanWrite before calling SetLength or Write on any stream.
- Never resize streams obtained from indexing filters.
- Copy to MemoryStream or a PackagePart write stream when mutation is needed.
- Centralize stream mutation behind helpers that assert writability.
When it happens
Trigger: Calling SetLength on a stream obtained from an indexing filter (UnsafeIndexingFilterStream), or via code that generically resizes streams passed to it.
Common situations: Utility code that calls SetLength before writing (e.g. truncating a buffer-style stream) applied to a filter stream; Stream wrappers that unconditionally resize;CanWrite==false was ignored.
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.PackagingWriteNotSupported
- Stream does not support SetLength.
- Stream does not support writing.
- A read or write operation references a location outside the…
- Cannot access Stream object because it was closed or…
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/789c29186ccbcc1c.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/MS/Internal/IO/Packaging/UnsafeIndexingFilterStream.cs:154
// The enum values of SeekOrigin match the STREAM_SEEK_* values. This
// convention is as good as carved in stone, so there's no need for a switch here.
_oleStream.Seek(offset, (int)origin, positionAddress);
return position;
}
/// <summary>
/// SetLength
/// </summary>
/// <exception cref="NotSupportedException">not supported</exception>
/// <remarks>
/// Not supported. No indexing filter should require it.
/// </remarks>
public override void SetLength(long newLength)
{
ThrowIfStreamDisposed();
throw new NotSupportedException(SR.StreamDoesNotSupportWrite);
}
/// <summary>
/// Write
/// </summary>
/// <exception cref="NotSupportedException">not supported</exception>
/// <remarks>
/// Not supported. No indexing filter should require it.
/// </remarks>
public override void Write(byte[] buf, int offset, int count)
{
ThrowIfStreamDisposed();
throw new NotSupportedException(SR.StreamDoesNotSupportWrite);
}
/// <summary>
/// Flush
/// </summary>View on GitHub (pinned to 81131a70a4)