stride3d/stride · error · InvalidCastException

Can not convert value to the required type

Error message

Can not convert value to the required type

What it means

NodeViewModel.ConvertValue throws InvalidCastException when TypeConverterHelper.TryConvert cannot convert the given value to the node view model's Type. It fires during value assignment when the incoming object is non-null and not convertible. This guards the view model against incompatible values.

Solutions

  1. Ensure the value's type matches the node's Type, or register a TypeConverter for it.
  2. Pre-convert with TypeConverterHelper.TryConvert and handle failure before assignment.
  3. Pass null instead of a non-convertible object if null is acceptable for the node.
  4. Check for a model/view-model type mismatch after refactoring.

Example fix

// before
nodeViewModel.Value = rawString; // InvalidCastException if not convertible
// after
if (TypeConverterHelper.TryConvert(rawString, nodeViewModel.Type, out var converted))
    nodeViewModel.Value = converted;
else
    log.Warn($"Cannot convert {rawString} to {nodeViewModel.Type}");
Defensive patterns

Strategy: type-guard

Validate before calling

if (value != null && !TypeConverterHelper.TryConvert(value, targetType, out _))
    throw new InvalidOperationException($"{value.GetType()} is not convertible to {targetType}");

Type guard

static bool IsConvertible(object value, Type targetType) =>
    value == null || TypeConverterHelper.TryConvert(value, targetType, out _);

Try / catch

try
{
    nodeViewModel.Value = value;
}
catch (InvalidCastException ex)
{
    logger.Warn(ex, "Value assignment rejected: type not convertible");
}

Prevention

When it happens

Trigger: Setting a NodeViewModel's value with an object whose type cannot be converted to the node's Type via TypeConverterHelper — e.g. assigning a string where a struct/color is expected and no type converter is registered.

Common situations: Property grid edits with free-text input for non-convertible types; binding a view model property to a source of mismatched type; custom types lacking registered type converters.

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


AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14). Data as JSON: /api/errors/5d6deed98998ab70. Report an issue: GitHub.

Appendix: source

Thrown at sources/presentation/Stride.Core.Presentation.Quantum/ViewModels/NodeViewModel.cs:588

        if (!IsDestroyed)
        {
            Refresh();
        }
        UpdateViewModelProperties();
        OnPropertyChanged(nameof(VisibleChildrenCount));

        OnPropertyChanged(nameof(NodeValue));
        owner.NotifyNodeChanged(this);

        valueChanging = false;
    }

    private object? ConvertValue(object value)
    {
        if (value == null)
            return null;
        if (!TypeConverterHelper.TryConvert(value, Type, out var convertedValue))
            throw new InvalidCastException("Can not convert value to the required type");
        return convertedValue;
    }

    private void AddChild(NodeViewModel child) => ChangeAndNotify(() => { child.Parent = this; ((ICollection<NodeViewModel>?)initializingChildren ?? children).Add(child); }, $"{GraphViewModel.HasChildPrefix}{child.Name}", child.Name);

    private void RemoveChild(NodeViewModel child) => ChangeAndNotify(() => { child.Parent = null; ((ICollection<NodeViewModel>?)initializingChildren ?? children).Remove(child); }, $"{GraphViewModel.HasChildPrefix}{child.Name}", child.Name);

    private void AddCommand(NodePresenterCommandWrapper command) => ChangeAndNotify(() => commands.Add(command), $"{GraphViewModel.HasCommandPrefix}{command.Name}", command.Name);

    private void RemoveCommand(NodePresenterCommandWrapper command) => ChangeAndNotify(() => commands.Remove(command), $"{GraphViewModel.HasCommandPrefix}{command.Name}", command.Name);

    private void AddAssociatedData(string key, object value) => ChangeAndNotify(() => associatedData.Add(key, value), $"{GraphViewModel.HasAssociatedDataPrefix}{key}", key);

    private void RemoveAssociatedData(string key) => ChangeAndNotify(() => associatedData.Remove(key), $"{GraphViewModel.HasAssociatedDataPrefix}{key}", key);

    private void ChangeAndNotify(Action changeAction, params string[] propertyNames)
    {
        ArgumentNullException.ThrowIfNull(changeAction);

View on GitHub (pinned to 96fad776d2)