stride3d/stride · error · InvalidOperationException

Exception of type 'System.InvalidOperationException' was…

Error message

Exception of type 'System.InvalidOperationException' was thrown.

What it means

During InstantiateGenericShader, when an OpTypeArray is found the builder looks up its Length id in the context buffer and expects an instruction to exist. If TryGetInstructionById fails, the invariant that array-length constants are present in the buffer is broken and a bare InvalidOperationException is thrown.

Solutions

  1. Ensure the array length constant (OpConstant) is emitted into the context buffer, not the main buffer, before instantiation.
  2. Regenerate the shader buffers from source if they come from a stale cache.
  3. If manipulating instructions manually, never remove the instruction whose result-id an OpTypeArray.Length references.

Example fix

// before
context.RemoveAt(instructionIndex); // removes constant later referenced by OpTypeArray.Length
// after (keep or replace preserving result id)
context.Replace(instructionIndex, new OpConstantInt(resultId, type, newValue));
Defensive patterns

Strategy: try-catch

Validate before calling

if (!shaderBuffers.Context.GetBuffer().TryGetInstructionById(typeArrayLengthId, out var len) || len.Op != Op.OpConstant)
    throw new InvalidOperationException($"Array length id {typeArrayLengthId} is not a constant in the context buffer");

Type guard

bool HasConstantLength(ShaderBuffers b, int lengthId) => b.Context.GetBuffer().TryGetInstructionById(lengthId, out var i) && i.Op == Op.OpConstant;

Try / catch

try { result = builder.InstantiateGenericShader(...); }
catch (InvalidOperationException ex) when (ex.StackTrace.Contains("InstantiateGenericShader")) { /* rebuild buffers from source and retry once */ }

Prevention

When it happens

Trigger: Instantiating a generic shader whose buffer contains an OpTypeArray whose Length result-id is not present in shaderBuffers.Context.GetBuffer() — the defining constant was dropped, lives in another buffer, or the id is stale.

Common situations: Arrays sized by a generic constant where the constant was replaced/removed during generic substitution; using a buffer pair (Context/Buffer) that got split incorrectly; cached shader buffers missing context instructions.

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/30965ccee9a474f7. Report an issue: GitHub.

Appendix: source

Thrown at sources/shaders/Stride.Shaders.Parsers/Spirv/Building/Builder.Class.cs:482

                            resolvedArgId = innerArgs[innerRef.Index];
                        else
                            break; // Can't resolve further
                    }

                    // Extract the resolved constant and its dependencies from the context buffer
                    var constantBuffer = SpirvContext.ExtractConstantFromBuffer(resolvedArgId, shaderBuffers.Context.GetBuffer());
                    // Remove the GenericReference and insert the resolved constant with the same ResultId
                    shaderBuffers.Context.RemoveAt(index);
                    shaderBuffers.Context.InsertWithoutDuplicates(ref index, genRef.ResultId, constantBuffer);
                    index--; // adjust for loop increment
                }
            }

            if (i.Op == Op.OpTypeArray && (OpTypeArray)i is { } typeArray)
            {
                // Make sure constant is a proper OpConstant (i.e. not an OpSpecConstant/OpSpecConstantOp)
                if (!shaderBuffers.Context.GetBuffer().TryGetInstructionById(typeArray.Length, out var lengthInstruction))
                    throw new InvalidOperationException();
                if (lengthInstruction.Op != Op.OpConstant)
                {
                    var expr = ConstantExpression.ParseFromBuffer(typeArray.Length, shaderBuffers.Context.GetBuffer(), shaderBuffers.Context);
                    if (expr.TryEvaluate(out var value) && value != null)
                    {
                        var resultType = lengthInstruction.Data.IdResultType!.Value;
                        var resultId = lengthInstruction.Data.IdResult!.Value;
                        if (value is int or long)
                            shaderBuffers.Context.Replace(lengthInstruction.Index, new OpConstant<int>(resultType, resultId, System.Convert.ToInt32(value)));
                        else if (value is float or double)
                            shaderBuffers.Context.Replace(lengthInstruction.Index, new OpConstant<float>(resultType, resultId, System.Convert.ToSingle(value)));
                    }
                }
            }
        }

        //Console.WriteLine($"[Shader] Instantiating {classNameWithGenerics}");

View on GitHub (pinned to 96fad776d2)