stride3d/stride · error · InvalidOperationException
Can't convert interface variable from
Error message
Can't convert interface variable from {sourceType} to {castType} What it means
BuiltinProcessor.ConvertInterfaceVariable converts an interface variable's value to a cast type by resizing component vectors. Conversion is only allowed when base scalar types match; if castBaseType != sourceBaseType (e.g. float vs int semantic variable) the conversion is undefined and it throws InvalidOperationException.
Solutions
- Match the base scalar type of the variable to the semantic's expected type (float for most SV_* positions, uint for sample masks, etc.)
- Insert an explicit conversion in the shader body (e.g. (int4)streams.Position) instead of relying on interface-variable conversion
- Check the builtin remapping table entry that produced the incompatible castType
- If conversion should be supported, extend ConvertInterfaceVariable to emit a numeric conversion instead of throwing
Example fix
// before int4 pos : SV_Position; // int vs float builtin // after float4 pos : SV_Position; // convert explicitly in body if int needed: var p = (int4)streams.Position;
Defensive patterns
Strategy: type-guard
Validate before calling
var (_, castBase) = ExtractSizeAndBaseType(castType);
var (_, srcBase) = ExtractSizeAndBaseType(sourceType);
if (castBase != srcBase) throw new InvalidOperationException($"Interface cast requires matching base types: {srcBase} vs {castBase}"); Type guard
bool IsConvertibleCast(SdslType source, SdslType cast) => ExtractSizeAndBaseType(source).BaseType == ExtractSizeAndBaseType(cast).BaseType;
Try / catch
try { var v = processor.ConvertInterfaceVariable(value, castType); } catch (InvalidOperationException ex) { logger.LogError(ex, "Builtin type conversion rejected"); throw; } Prevention
- Type semantic variables to match their system-value semantics (float4 for SV_Position, etc.)
- Avoid int/float mixing between builtin tables and interface structs
- Insert explicit conversions in shader body instead of interface-level casts
When it happens
Trigger: Applying a semantic/builtin cast where the target and source differ in base scalar type — e.g. a float4 semantic read and reinterpreted as an int4 (SV_Position to integer), or uint vs float builtin remaps.
Common situations: Shader code assigning a builtin/system-value to a variable of a different scalar type; remapping tables mapping SV_* semantics to differently typed variables; accidental int/float mixup in an interface struct.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- Two variables with same semantic
- 64bit integers
- An unknown EffectParameterClass was found.
- antialiasShaderName
- Assign back to matrix swizzle is not implemented yet
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/afff4a14dd602656.
Report an issue: GitHub.
Appendix: source
Thrown at sources/shaders/Stride.Shaders.Parsers/Spirv/Processing/Interfaces/Generation/BuiltinProcessor.cs:54
/// <summary>
/// Converts interface variables between types, handling vector and array size mismatches.
/// Used when builtin types have different sizes than shader types.
/// </summary>
public static int ConvertInterfaceVariable(
SpirvBuffer buffer,
SpirvContext context,
SymbolType sourceType,
SymbolType castType,
int value)
{
if (sourceType == castType)
return value;
var (castSize, castBaseType) = ExtractSizeAndBaseType(castType);
var (sourceSize, sourceBaseType) = ExtractSizeAndBaseType(sourceType);
if (castBaseType != sourceBaseType)
throw new InvalidOperationException($"Can't convert interface variable from {sourceType} to {castType}");
Span<int> components = stackalloc int[castSize];
for (int i = 0; i < castSize; ++i)
{
components[i] = i < sourceSize
? (sourceType is ScalarType ? value : buffer.Add(new OpCompositeExtract(context.GetOrRegister(sourceBaseType), context.Bound++, value, [i])).ResultId)
: context.CreateDefaultConstantComposite(sourceBaseType).Id;
}
return castType is ScalarType
? components[0]
: buffer.Add(new OpCompositeConstruct(context.GetOrRegister(castType), context.Bound++, new(components))).ResultId;
(int Size, SymbolType baseType) ExtractSizeAndBaseType(SymbolType castType)
{
return castType switch
{View on GitHub (pinned to 96fad776d2)