dotnet/wpf · error · NotSupportedException

Streams for exposure as ILockBytes must be seekable.

Error message

Streams for exposure as ILockBytes must be seekable.

What it means

UnsafeLockBytesOnStream wraps a Stream to expose it as an ILockBytes for native compound-file APIs. The underlying stream must support seeking (random access); a non-seekable stream (e.g. network stream, pipe, or a forward-only stream) causes NotSupportedException with the 'Streams for exposure as ILockBytes must be seekable' message.

Solutions

  1. Wrap the non-seekable stream in a seekable buffer: copy it into a MemoryStream or a temp FileStream before creating the compound file.
  2. Verify stream.CanSeek before constructing, and fail fast with a clear error if false.
  3. For long content, spool to disk (FileStream) rather than holding it all in memory.

Example fix

// before
var package = Package.Open(nonSeekableNetworkStream);
// after
using (var buffered = new MemoryStream()) {
    nonSeekableNetworkStream.CopyTo(buffered);
    buffered.Position = 0;
    var package = Package.Open(buffered);
}
Defensive patterns

Strategy: validation

Validate before calling

if (!underlyingStream.CanSeek) throw new ArgumentException(nameof(underlyingStream), "stream must be seekable to back ILockBytes");

Try / catch

try { CreateOnStream(stream); }
catch (NotSupportedException ex) { /* buffer into MemoryStream/FileStream and retry */ }

Prevention

When it happens

Trigger: Passing a non-seekable Stream (CanSeek == false) — such as an unbuffered network stream, stdin/stdout wrapper, or decompression stream — into UnsafeLockBytesOnStream / UnsafeNativeCompoundFileCommon.CreateOnStream.

Common situations: Opening a Package/ZipPackage directly over an HTTP response stream or crypto stream without buffering it into a MemoryStream or FileStream first.

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/950224e92f8e2f34. Report an issue: GitHub.

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/WindowsBase/MS/Internal/IO/Packaging/CompoundFile/PrivateUnsafeNativeCompoundFileMethods.cs:71

            int grfMode,       // Specifies the access mode for opening the storage object
            int stgfmt,        // Specifies the storage file format, 5 is DocFile
            int grfAttrs,      // Reserved; must be zero
            IntPtr pStgOptions,// Pointer to STGOPTIONS, not marshalled, must use NULL.
            IntPtr reserved2,  // Reserved; must be null
            ref Guid riid,     // Specifies the GUID of the interface pointer
            out UnsafeNativeIStorage ppObjectOpen       //Pointer to an interface pointer
            );    

        [DllImport("ole32.dll")]
        internal static extern int PropVariantClear(ref PROPVARIANT pvar);

        internal class UnsafeLockBytesOnStream : UnsafeNativeILockBytes, IDisposable
        {
            internal UnsafeLockBytesOnStream( Stream underlyingStream )
            {
                if( !underlyingStream.CanSeek )
                {
                    throw new NotSupportedException(
                        SR.ILockBytesStreamMustSeek);
                }

                _baseStream = underlyingStream;
            }
            
            public void Dispose()
            {              
                Dispose(true);
                GC.SuppressFinalize(this);
            }

            /// <summary>
            /// Dispose(bool)
            /// </summary>
            /// <param name="disposing"></param>
            protected virtual void Dispose(bool disposing)
            {

View on GitHub (pinned to 81131a70a4)