dotnet/wpf · error · InvalidOperationException

SR.Effect_ShaderSeekableStream

Error message

SR.Effect_ShaderSeekableStream

What it means

PixelShader.SetStreamSource (or the URI load path) received a stream whose CanSeek is false. The loader needs source.Length to size the bytecode buffer, which only works on seekable streams, so it throws InvalidOperationException with SR.Effect_ShaderSeekableStream.

Solutions

  1. Buffer the stream into a MemoryStream first: var ms = new MemoryStream(); source.CopyTo(ms); ms.Position = 0; shader.SetStreamSource(ms)
  2. Read the bytes and load from a seekable wrapper (new MemoryStream(byteArray))
  3. Prefer loading bytecode from an embedded resource stream that is seekable
  4. Avoid removing MemoryStream from the shader-loading path; the loader requires Length

Example fix

// before
shader.SetStreamSource(responseStream); // network stream, not seekable: throws

// after
var ms = new MemoryStream();
responseStream.CopyTo(ms);
ms.Position = 0;
shader.SetStreamSource(ms); // seekable
Defensive patterns

Strategy: validation

Validate before calling

if (source == null) throw new ArgumentNullException(nameof(source));
if (!source.CanSeek)
{
    var buffered = new MemoryStream();
    source.CopyTo(buffered);
    buffered.Position = 0;
    source = buffered;
}
shader.SetStreamSource(source);

Type guard

static bool IsSeekable(Stream s) => s != null && s.CanSeek;

Try / catch

try { shader.SetStreamSource(stream); }
catch (InvalidOperationException ex) when (ex.Message.Contains("seek"))
{
    var ms = new MemoryStream();
    stream.CopyTo(ms);
    ms.Position = 0;
    shader.SetStreamSource(ms);
}

Prevention

When it happens

Trigger: Calling shader.SetStreamSource(networkStream / non-seekable decompression stream); passing a forward-only stream (e.g. raw HttpResponse stream, streaming pipeline) as shader bytecode source.

Common situations: Downloading .ps bytecode directly from HTTP and passing the response stream; wrapping shader bytes in a CryptoStream or GZipStream chain that lost seekability; memory pressure code that swapped MemoryStream for a pipe.

Understand the failure class

Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.

Related errors


AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14). Data as JSON: /api/errors/e23428ecb91754a1. Report an issue: GitHub.

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/Effects/PixelShader.cs:123

            finally
            {
                stream?.Dispose();
            }
        }

        /// <summary>
        /// Reads the byte code for the pixel shader into a local byte array. If the stream is null, the byte array
        /// will be empty (length 0). The compositor will use an identity shader.
        /// </summary>
        private void LoadPixelShaderFromStreamIntoMemory(Stream source) 
        {
            _shaderBytecode = null;

            if (source != null)
            {
                if (!source.CanSeek)
                {
                    throw new InvalidOperationException(SR.Effect_ShaderSeekableStream);
                }

                int len = (int)source.Length;  // only works on seekable streams.

                if (len % sizeof(int) != 0)
                {
                    throw new InvalidOperationException(SR.Effect_ShaderBytecodeSize);
                }
                
                BinaryReader br = new BinaryReader(source);
                _shaderBytecode = new byte[len];
                int lengthRead = br.Read(_shaderBytecode, 0, (int)len);

                //
                // The first 4 bytes contain version info in the form of
                // [Minor][Major][xx][xx]
                //
                if (_shaderBytecode != null && _shaderBytecode.Length > 3)

View on GitHub (pinned to 81131a70a4)