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

  1. Do not call SetLength on this stream; it is read-only by contract.
  2. Check stream.CanWrite / this stream type before resizing and copy to a writable MemoryStream if mutation is needed.
  3. 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

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


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)