stride3d/stride · error · InvalidOperationException
Cannot find type for composite constant type id
Error message
Cannot find type for composite constant type id {typeId} What it means
ConstantExpression.ParseInstruction throws this InvalidOperationException when parsing an OpConstantComposite/OpSpecConstantComposite whose result-type id is not present in context.ReverseTypes. Unlike the scalar path (which looks up the type in the buffer), composite parsing needs the parsed SymbolType registered in the context to build a CompositeConstExpr.
Solutions
- Use the same SpirvContext that emitted/registered the composite type (check context.ReverseTypes for the typeId before parsing).
- Register the composite type in the context (context.GetOrRegister(symbolType)) so ReverseTypes contains the id.
- Verify you are not mixing ids from a different buffer/context pair.
- For cross-context transfer, parse in the source context first, then Emit into the target context.
Example fix
// before: fresh context can't resolve the composite type var ctx = new SpirvContext(); var expr = ConstantExpression.ParseFromBuffer(vecConstId, buffer, ctx); // throws // after: parse with the original context that owns the types var expr = ConstantExpression.ParseFromBuffer(vecConstId, buffer, originalContext);
Defensive patterns
Strategy: validation
Validate before calling
static bool CompositeTypeRegistered(SpirvContext context, SpirvBuffer buffer, int compositeConstId)
=> buffer.TryGetInstructionById(compositeConstId, out var inst)
&& inst.Op is Op.OpConstantComposite or Op.OpSpecConstantComposite
&& context.ReverseTypes.ContainsKey(inst.Data.Memory.Span[1]); Try / catch
try
{
var expr = ConstantExpression.ParseFromBuffer(vecId, buffer, context);
}
catch (InvalidOperationException ex) when (ex.Message.Contains("composite constant type id"))
{
// parse with the owning context instead, or register the type first
} Prevention
- Parse composites with the same SpirvContext that registered their types.
- Check context.ReverseTypes before parsing composite constants.
- Transfer across contexts by parsing then Emit, not by sharing raw ids.
When it happens
Trigger: Calling ConstantExpression.ParseFromBuffer on a composite constant (vector/array/struct) when the SpirvContext was not the one that emitted the type — e.g. a fresh or partial context whose ReverseTypes map lacks the type id, or parsing a composite extracted from a foreign buffer.
Common situations: Using a newly constructed SpirvContext with a buffer produced by another context; splicing composite constants across buffers; EmitToBuffer round-trips where the composite type was never registered in the temp context; wrong typeId due to buffer mixing.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- Cannot find type instruction for id
- Unsupported float width
- Unsupported constant type
- Unsupported OpSpecConstantOp inner op
- Cannot parse constant expression from
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/0e1341bc8bfe3fbb.
Report an issue: GitHub.
Appendix: source
Thrown at sources/shaders/Stride.Shaders.Parsers/Core/ConstantExpression.cs:150
case Op.OpConstantStringSDSL:
{
var operand = inst.Data.Get("literalString");
return new StringConstExpr(operand.ToLiteral<string>());
}
case Op.OpGenericParameterSDSL:
case Op.OpGenericReferenceSDSL:
{
var genParam = (OpGenericParameterSDSL)inst;
return new GenericParamExpr(genParam.Index, genParam.DeclaringClass);
}
case Op.OpConstantComposite:
case Op.OpSpecConstantComposite:
{
var typeId = inst.Data.Memory.Span[1];
if (!context.ReverseTypes.TryGetValue(typeId, out var compositeType))
throw new InvalidOperationException($"Cannot find type for composite constant type id {typeId}");
var constituents = inst.Data.Memory.Span[3..];
var components = new ConstantExpression[constituents.Length];
for (int i = 0; i < constituents.Length; i++)
components[i] = ParseFromBuffer(constituents[i], buffer, context);
return new CompositeConstExpr(compositeType, components);
}
case Op.OpSpecConstantOp:
{
var op = (Op)inst.Data.Memory.Span[3];
switch (op)
{
// Conversions (unary)
case Op.OpConvertFToS:
case Op.OpConvertFToU:
case Op.OpConvertSToF:
case Op.OpConvertUToF:
case Op.OpSNegate:View on GitHub (pinned to 96fad776d2)