stride3d/stride · error · InvalidOperationException
ValueType is not one of the expected types.
Error message
ValueType is not one of the expected types.
What it means
ProfilingCustomValue.ToObject() converts the stored union (IntValue/FloatValue/LongValue/DoubleValue) back to object based on ValueType. If ValueType holds anything but those four types, the internal invariant is broken and it throws InvalidOperationException naming ValueType.
Solutions
- Set the value only through the implicit operators (int/float/long/double) so ValueType is always valid
- If you need another type, extend ValueType checks in ToObject and add a corresponding implicit operator
- Default-initialize ValueType to the matching type when constructing manually
Example fix
// before
new ProfilingCustomValue { ValueType = typeof(string), /* no string field */ }
// after
ProfilingCustomValue v = 42; // sets ValueType = typeof(int), IntValue = 42 Defensive patterns
Strategy: validation
Validate before calling
var supported = new[]{ typeof(int), typeof(float), typeof(long), typeof(double) };
object value = supported.Contains(v.ValueType) ? v.ToObject() : throw new InvalidOperationException(); Type guard
bool isKnownCustomValue(ProfilingCustomValue v) =>
v.ValueType == typeof(int) || v.ValueType == typeof(float) || v.ValueType == typeof(long) || v.ValueType == typeof(double); Try / catch
try { obj = customValue.ToObject(); }
catch (InvalidOperationException) { obj = null; /* log invariant breach */ } Prevention
- Only build ProfilingCustomValue via its implicit operators
- Never hand-assign ValueType in initializers
- Update both ValueType checks and operators together when extending types
When it happens
Trigger: Constructing a ProfilingCustomValue with object initializer/struct field assignment setting ValueType to e.g. typeof(string), typeof(bool) or leaving it null while setting a value field; misuse of the struct outside its implicit-operator API.
Common situations: Custom profiling code that bypasses the implicit conversions from int/float/long/double and hand-rolls the struct; serialization round-trips that restore ValueType incorrectly; adding support for a new type without updating ToObject.
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
- A PackageViewModel cannot contain two isntances of…
- A transaction failed to be created.
- A UIPage asset can't have more than one root.
- All should have hashsets associated to them
- An id is both marked as deleted and associated to a key of…
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/427ba31c1b1fdfea.
Report an issue: GitHub.
Appendix: source
Thrown at sources/core/Stride.Core/Diagnostics/ProfilingCustomValue.cs:32
[FieldOffset(0)]
public float FloatValue;
[FieldOffset(0)]
public long LongValue;
[FieldOffset(0)]
public double DoubleValue;
[FieldOffset(8)]
public Type ValueType;
public readonly object ToObject()
{
if (ValueType == typeof(int)) return IntValue;
else if (ValueType == typeof(float)) return FloatValue;
else if (ValueType == typeof(long)) return LongValue;
else if (ValueType == typeof(double)) return DoubleValue;
else throw new InvalidOperationException($"{nameof(ValueType)} is not one of the expected types.");
}
public static implicit operator ProfilingCustomValue(int value)
{
return new ProfilingCustomValue { IntValue = value, ValueType = typeof(int) };
}
public static implicit operator ProfilingCustomValue(float value)
{
return new ProfilingCustomValue { FloatValue = value, ValueType = typeof(float) };
}
public static implicit operator ProfilingCustomValue(long value)
{
return new ProfilingCustomValue { LongValue = value, ValueType = typeof(long) };
}
public static implicit operator ProfilingCustomValue(double value)View on GitHub (pinned to 96fad776d2)