stride3d/stride · error · InvalidOperationException

Vulkan: bytecode is expected to be the same for all stages

Error message

Vulkan: bytecode is expected to be the same for all stages

What it means

CreateShaderStages creates a single Vulkan VkShaderModule from one stage's SPIR-V bytecode and expects every stage in the array to reference identical bytecode; if any stage.Data differs it throws InvalidOperationException. The Vulkan backend here assumes all stages of a pipeline share the same module bytecode layout, so divergent stage data is an internal invariant violation rather than a user-facing configuration issue.

Solutions

  1. Regenerate the effect bytecode with the Stride effect compiler so all stages carry consistent data.
  2. Check that the EffectBytecode was not assembled or edited by hand.
  3. If custom pipeline code, create separate shader modules per stage instead of relying on shared bytecode.
  4. Verify asset pipeline output isn't mixing bytecode from different effect versions (clear the effect log/cache).
Defensive patterns

Strategy: validation

Validate before calling

var first = bytecode.Stages[0].Data;
if (bytecode.Stages.Any(s => !s.Data.SequenceEqual(first)))
    throw new InvalidOperationException("Effect bytecode data differs across stages");

Type guard

bool HasConsistentBytecode(EffectBytecode bc) => bc.Stages.All(s => s.Data.AsSpan().SequenceEqual(bc.Stages[0].Data));

Try / catch

try { pipeline.CreateShaderStages(stages); }
catch (InvalidOperationException ex) when (ex.Message.Contains("bytecode is expected to be the same")) { log.Error("Inconsistent stage bytecode in effect", ex); throw; }

Prevention

When it happens

Trigger: Calling CreateShaderStages (via the 'stages' pipeline creation path) with an EffectBytecode whose ShaderStages entries have differing Data arrays (different SPIR-V blobs per stage).

Common situations: A corrupted or hand-constructed effect bytecode; an effect compiler bug emitting per-stage distinct bytecode where the pipeline expects a shared module; mixing compiled modules from different effect compilations into one PipelineState.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14). Data as JSON: /api/errors/138f0e99ea6467f0. Report an issue: GitHub.

Appendix: source

Thrown at sources/engine/Stride.Graphics/Vulkan/PipelineState.Vulkan.cs:393

            GraphicsDevice.CheckResult(GraphicsDevice.NativeDeviceApi.vkCreatePipelineLayout(GraphicsDevice.NativeDevice, &pipelineLayoutCreateInfo, allocator: null, out NativeLayout));
        }

        private unsafe VkPipelineShaderStageCreateInfo[] CreateShaderStages(PipelineStateDescription pipelineStateDescription)
        {
            var stages = pipelineStateDescription.EffectBytecode.Stages;
            var nativeStages = new VkPipelineShaderStageCreateInfo[stages.Length];

            IsCompute = false;

            // Create shader module (shared by all stages)
            var shaderBytecode = stages[0].Data;
            GraphicsDevice.CheckResult(GraphicsDevice.NativeDeviceApi.vkCreateShaderModule(GraphicsDevice.NativeDevice, shaderBytecode, allocator: null, out var shaderModule));

            for (int i = 0; i < stages.Length; i++)
            {
                var stage = stages[i];
                if (!stage.Data.SequenceEqual(shaderBytecode))
                    throw new InvalidOperationException("Vulkan: bytecode is expected to be the same for all stages");

                if (stage.Stage == ShaderStage.Compute)
                    IsCompute = true;

                fixed (byte* entryPointPointer = &stage.EntryPoint[0])
                {
                    // Create stage
                    nativeStages[i] = new VkPipelineShaderStageCreateInfo
                    {
                        sType = VkStructureType.PipelineShaderStageCreateInfo,
                        stage = VulkanConvertExtensions.Convert(stages[i].Stage),
                        pName = entryPointPointer,
                        module = shaderModule,
                    };
                }
            }

            return nativeStages;

View on GitHub (pinned to 96fad776d2)