dotnet/wpf · error · InvalidOperationException

SR.Effect_ShaderBytecodeSize

Error message

SR.Effect_ShaderBytecodeSize

What it means

PixelShader.LoadPixelShaderFromStreamIntoMemory reads the stream length and requires the shader bytecode length to be a multiple of sizeof(int) (4 bytes). If the seekable stream's length is not 4-byte aligned, an InvalidOperationException with Effect_ShaderBytecodeSize is thrown. HLSL bytecode is always emitted in 4-byte-aligned chunks, so a non-aligned stream is corrupt or not real shader bytecode.

Solutions

  1. Compile the HLSL with fxc into pixel-shader bytecode (e.g. /T ps_2_0) and embed that .ps file, not the .fx source.
  2. Verify the stream length is a multiple of 4: if (stream.Length % 4 != 0) reject/repair it before assigning to PixelShader.StreamSource.
  3. Ensure the resource build action (Resource) and copy settings produce the full untruncated bytecode in the assembly.
  4. Check the shader file loads completely (seek to end, check Length) and is not empty or corrupt.

Example fix

// before
pixelShader.UriSource = new Uri("pack://application:,,,/shaders/effect.fx");
// after
pixelShader.UriSource = new Uri("pack://application:,,,/shaders/effect.ps"); // compiled fxc output, 4-byte aligned
Defensive patterns

Strategy: validation

Validate before calling

using (var s = File.OpenRead(shaderPath))
{
    if (!s.CanSeek || s.Length == 0 || s.Length % 4 != 0)
        throw new InvalidOperationException("Shader stream is not valid 4-byte-aligned bytecode: " + shaderPath);
}
pixelShader.UriSource = new Uri("pack://application:,,,/shaders/effect.ps");

Type guard

static bool IsValidShaderStream(Stream s) => s != null && s.CanSeek && s.Length > 0 && s.Length % sizeof(int) == 0;

Prevention

When it happens

Trigger: Setting PixelShader.UriSource to a resource whose content is not valid ps/pshader bytecode, or assigning a StreamSource whose length is not divisible by 4 (truncated file, wrong file, text file, partially downloaded payload) before reading into _shaderBytecode.

Common situations: Pointing UriSource at a .fx source file instead of the compiled .ps bytecode; a build/packaging step truncating the shader resource; loading a shader from a network stream that was cut off; copying the shader file with a wrong size.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


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

Appendix: source

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

        /// 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)
                {
                    ShaderMajorVersion = _shaderBytecode[1];
                    ShaderMinorVersion = _shaderBytecode[0];
                }
                else
                {
                    ShaderMajorVersion = ShaderMinorVersion = 0;

View on GitHub (pinned to 81131a70a4)