dotnet/wpf · error · InvalidOperationException

SR.SeekNotSupported

Error message

SR.SeekNotSupported

What it means

The CompressEmulationStream constructor requires the base stream to support seeking, because emulating compression on top of it needs both seek and read. A non-seekable base stream causes an InvalidOperationException with SR.SeekNotSupported.

Solutions

  1. Buffer the base stream into a seekable medium first (MemoryStream or FileStream) before constructing.
  2. Check baseStream.CanSeek before constructing and fail with a clear message.
  3. For network sources, download to a temp file and open that.

Example fix

// before
var es = new CompressEmulationStream(networkStream, tempStream, transformer);
// after
if (!networkStream.CanSeek)
{
    var buffered = new MemoryStream();
    networkStream.CopyTo(buffered);
    buffered.Position = 0;
    networkStream = buffered;
}
var es = new CompressEmulationStream(networkStream, tempStream, transformer);
Defensive patterns

Strategy: validation

Validate before calling

static Stream AsSeekable(Stream source)
{
    if (source.CanSeek) return source;
    var ms = new MemoryStream();
    source.CopyTo(ms);
    ms.Position = 0;
    return ms;
}

Type guard

bool IsSeekableReadable(Stream s) => s != null && s.CanSeek && s.CanRead;

Try / catch

try { var es = new CompressEmulationStream(baseStream, tempStream, transformer); }
catch (InvalidOperationException e) { throw new InvalidDataException("Base stream must be seekable and readable; buffer it first", e); }

Prevention

When it happens

Trigger: Constructing CompressEmulationStream with a baseStream whose CanSeek is false — e.g. a network stream, a forward-only decompressed stream, or a write-only FileStream.

Common situations: Wrapping HTTP response streams or pipes; opening packages directly over non-seekable sources; forwarding a stream from a download before buffering it.

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/2220d6b040c889a3. Report an issue: GitHub.

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/WindowsBase/MS/Internal/IO/Packaging/CompressEmulationStream.cs:254

        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="baseStream">part stream - not closed - caller determines lifetime</param>
        /// <param name="position">current logical stream position</param>
        /// <param name="tempStream">should be an IsolatedStorageFileStream - not closed - caller determines lifetime</param>
        /// <param name="transformer">class that does the compression/decompression</param>
        /// <remarks>This class should only invoked when emulation is required.  
        /// Does not close any given stream, even when Close is called. This means that it requires
        /// another wrapper Stream class.</remarks>
        internal CompressEmulationStream(Stream baseStream, Stream tempStream, long position, IDeflateTransform transformer)
        {
            ArgumentOutOfRangeException.ThrowIfNegative(position);

            ArgumentNullException.ThrowIfNull(baseStream);

            // seek and read required for emulation
            if (!baseStream.CanSeek)
                throw new InvalidOperationException(SR.SeekNotSupported);

            if (!baseStream.CanRead)
                throw new InvalidOperationException(SR.ReadNotSupported);

            ArgumentNullException.ThrowIfNull(tempStream);
            ArgumentNullException.ThrowIfNull(transformer);

            _baseStream = baseStream;
            _tempStream = tempStream;
            _transformer = transformer;

            // extract to temporary stream
            _baseStream.Position = 0;
            _tempStream.Position = 0;
            _transformer.Decompress(baseStream, tempStream);

            // seek to the current logical position
            _tempStream.Position = position;

View on GitHub (pinned to 81131a70a4)