stride3d/stride · error · NotImplementedException
Unsupported constant type
Error message
Unsupported constant type {typeInst.Op} What it means
ConstantExpression.ParseInstruction throws this NotImplementedException when an OpConstant/OpSpecConstant's result type instruction is neither OpTypeInt nor OpTypeFloat. SPIR-V constants of other types (e.g. OpTypeBool, vectors, structs) are not handled by the scalar constant branch, so the parser refuses to build a ConstantExpression for them.
Solutions
- Verify with spirv-dis that the id passed to ParseFromBuffer is a scalar int/float constant, not a bool or composite.
- Handle boolean constants (OpConstantTrue/OpConstantFalse) before reaching this branch — they are parsed separately as BoolConstExpr.
- If the constant is composite, ensure it comes through the OpConstantComposite branch instead.
- If a new scalar type must be supported, add a branch for its type op in ConstantExpression.cs:126.
Example fix
// before: ParseFromBuffer(boolConstantId, ...) -> OpConstant true, type OpTypeBool -> throws
// after: check the opcode first
if (buffer.TryGetInstructionById(id, out var inst) && inst.Op == Op.OpConstantTrue)
return new BoolConstExpr(true); // or use the constant only when it is an int/float scalar Defensive patterns
Strategy: type-guard
Validate before calling
static bool IsScalarIntOrFloatConstant(SpirvBuffer buffer, int id)
{
if (!buffer.TryGetInstructionById(id, out var inst)) return false;
if (inst.Op is not (Op.OpConstant or Op.OpSpecConstant)) return false;
var typeId = inst.Data.Memory.Span[1];
return buffer.TryGetInstructionById(typeId, out var t)
&& t.Op is Op.OpTypeInt or Op.OpTypeFloat;
} Type guard
static bool IsScalarConstantType(OpDataIndex typeInst)
=> typeInst.Op is Op.OpTypeInt or Op.OpTypeFloat; Try / catch
try
{
var expr = ConstantExpression.ParseFromBuffer(id, buffer, context);
}
catch (NotImplementedException)
{
// constant type is bool/composite; route to the appropriate parser branch or skip
} Prevention
- Check the opcode of the target instruction before calling ParseFromBuffer.
- Parse bool constants via OpConstantTrue/OpConstantFalse and composites via the composite branch.
- Keep to scalar int/float spec constants for array sizes and generic arguments.
When it happens
Trigger: Calling ConstantExpression.ParseFromBuffer on an id whose instruction is OpConstant/OpSpecConstant but whose result-type id resolves to a type instruction like OpTypeBool, OpTypeVector, or OpTypeStruct — e.g. extracting an 'array size' or generic argument that is actually a boolean or composite constant.
Common situations: Shader code using a bool spec-constant where an int is expected; pointing ParseFromBuffer at the wrong id in the buffer (a composite rather than scalar constant); SPIR-V produced by another compiler that models constants with types the SDSL parser never anticipated.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- Unsupported OpSpecConstantOp inner op
- Unsupported float width
- Cannot parse constant expression from
- Cannot find type instruction for id
- Cannot find type for composite constant type id
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/a9b0dcde8921ace9.
Report an issue: GitHub.
Appendix: source
Thrown at sources/shaders/Stride.Shaders.Parsers/Core/ConstantExpression.cs:127
{ Width: 64, Signedness: 1 } => operand.ToLiteral<long>(),
_ => throw new NotImplementedException($"Unsupported int width {type.Width}"),
};
return new IntConstExpr(val);
}
else if (typeInst.Op == Op.OpTypeFloat)
{
var type = new OpTypeFloat(typeInst);
double val = type switch
{
{ Width: 16 } => (double)operand.ToLiteral<Half>(),
{ Width: 32 } => operand.ToLiteral<float>(),
{ Width: 64 } => operand.ToLiteral<double>(),
_ => throw new NotImplementedException($"Unsupported float width {type.Width}"),
};
return new FloatConstExpr(val);
}
else
throw new NotImplementedException($"Unsupported constant type {typeInst.Op}");
}
throw new InvalidOperationException($"Cannot find type instruction for id {typeId}");
}
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:View on GitHub (pinned to 96fad776d2)