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

  1. Set the value only through the implicit operators (int/float/long/double) so ValueType is always valid
  2. If you need another type, extend ValueType checks in ToObject and add a corresponding implicit operator
  3. 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

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


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)