stride3d/stride · error · InvalidOperationException

{ex.Message} (bytecode {stages[0].Id} [{entryPoints}])

Error message

{ex.Message} (bytecode {stages[0].Id} [{entryPoints}])

What it means

When PipelineState.Recreate() fails, this catch block rethrows the underlying InvalidOperationException with added diagnostic context: the effect bytecode's stage id and the list of shader entry points (stage:name pairs). The original exception is preserved as InnerException. It exists to make pipeline (re)creation failures attributable to a specific shader bytecode, which is invaluable when debugging effects that fail only at runtime re-creation (e.g. after device loss).

Solutions

  1. Inspect the InnerException for the root cause (it contains the original message).
  2. Verify the EffectBytecode's stages and entry point names match the compiled shader sources.
  3. Recompile/reimport the effect (check EffectBytecode generation in the effect compiler) and rebuild assets.
  4. If it occurs after device loss, verify the pipeline can be rebuilt with the same bytecode on the new device.
Defensive patterns

Strategy: try-catch

Validate before calling

// verify bytecode entry points before pipeline creation
foreach (var stage in bytecode.Stages)
    if (stage.EntryPoint == null || stage.EntryPoint.Length == 0)
        throw new InvalidOperationException($"Stage {stage.Stage} missing entry point");

Type guard

bool HasStages(PipelineStateDescription d) => d.EffectBytecode?.Stages is { Length: > 0 };

Try / catch

try { pipeline = new PipelineState(device, desc); }
catch (InvalidOperationException ex) {
    log.Error($"Pipeline creation failed for bytecode {ex.InnerException?.Message}", ex);
    // ex.Message includes bytecode id + entry points; ex.InnerException has root cause
}

Prevention

When it happens

Trigger: Any InvalidOperationException thrown inside RecreateInner() during PipelineState creation or OnRecreate (e.g. missing root signature, invalid shader stages, driver rejection) while Description.EffectBytecode has at least one stage.

Common situations: Shader compilation/compilation-effect mismatch; pipeline state referencing an effect bytecode whose entry points don't match compiled shaders; device-lost recovery path (OnRecreate) failing after a GPU reset.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


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

Appendix: source

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

        internal PipelineState(GraphicsDevice graphicsDevice, PipelineStateDescription pipelineStateDescription) : base(graphicsDevice)
        {
            Description = pipelineStateDescription.Clone();
            Recreate();
        }

        private unsafe void Recreate()
        {
            // Note: important to pin this so that stages[x].Name is valid during this whole function
            try
            {
                fixed (void* defaultEntryPointData = defaultEntryPoint) // null if array is empty or null
                    RecreateInner();
            }
            catch (InvalidOperationException ex) when (Description.EffectBytecode?.Stages is { Length: > 0 } stages)
            {
                var entryPoints = string.Join(", ", stages.Select(s => $"{s.Stage}:{Encoding.UTF8.GetString(s.EntryPoint).TrimEnd('\0')}"));
                throw new InvalidOperationException($"{ex.Message} (bytecode {stages[0].Id} [{entryPoints}])", ex);
            }
        }

        private unsafe void RecreateInner()
        {
            if (Description.RootSignature == null)
                return;

            CreatePipelineLayout(Description);

            // Create shader stages
            var stages = CreateShaderStages(Description);

            if (IsCompute)
            {
                fixed (VkPipelineShaderStageCreateInfo* fStages = stages)
                {
                    var createInfo = new VkComputePipelineCreateInfo

View on GitHub (pinned to 96fad776d2)