stride3d/stride · error · ArgumentOutOfRangeException

This method must be invoked with at least one property name.

Error message

This method must be invoked with at least one property name.

What it means

The private SetValue<T>(ref field, ...) core setter requires at least one property name so the change can be broadcast and journaled. An empty params string[] is rejected with ArgumentOutOfRangeException before any mutation happens.

Solutions

  1. Always pass at least one property name, typically nameof(MyProperty)
  2. Validate the properties array is non-empty before forwarding
  3. Default a missing name to the calling property via CallerMemberName where applicable
  4. Add a debug assert at the public wrapper to fail fast in development

Example fix

// before
SetValue(ref name, value); // throws: no property name
// after
SetValue(ref name, value, nameof(Name));
Defensive patterns

Strategy: validation

Validate before calling

if (propertyNames == null || propertyNames.Length == 0)
    throw new ArgumentException("At least one property name is required.");

Try / catch

try { vm.SetValue(ref field, value, propertyName); }
catch (ArgumentOutOfRangeException) { /* missing property name — fix call site */ }

Prevention

When it happens

Trigger: Calling a public setter helper (e.g. SetValue<T>(ref T field, T value, ...) or Set/SetValue wrappers) with no property names, or forwarding a dynamically built propertyNames array that ended up empty.

Common situations: Programmatically constructing the params array from a collection that was empty; forgetting to pass the property name to a SetValue overload; refactoring that dropped the nameof(...) argument.

Related errors


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

Appendix: source

Thrown at sources/presentation/Stride.Core.Presentation/ViewModels/EditableViewModel.cs:212

    protected virtual Operation CreatePropertyChangeOperation(string displayName, string propertyName, object? preEditValue)
    {
        var operation = new PropertyChangeOperation(propertyName, this, preEditValue, Dirtiables);
        UndoRedoService.SetName(operation, displayName);
        return operation;
    }

    protected virtual Operation CreateCollectionChangeOperation(string displayName, IList list, NotifyCollectionChangedEventArgs args)
    {
        var operation = new CollectionChangeOperation(list, args, Dirtiables);
        UndoRedoService.SetName(operation, displayName);
        return operation;
    }

    private bool SetValue<T>(ref T field, T value, Action? updateAction, bool createTransaction, params string[] propertyNames)
    {
        if (propertyNames.Length == 0)
            throw new ArgumentOutOfRangeException(nameof(propertyNames), "This method must be invoked with at least one property name.");

        if (!EqualityComparer<T>.Default.Equals(field, value))
        {
            ITransaction? transaction = null;
            if (!UndoRedoService.UndoRedoInProgress && createTransaction)
            {
                transaction = UndoRedoService.CreateTransaction();
                var concatPropertyName = string.Join(", ", propertyNames.Where(x => !uncancellableChanges.Contains(x)).Select(s => $"'{s}'"));
                UndoRedoService.SetName(transaction, $"Update property {concatPropertyName}");
            }
            try
            {
                return base.SetValue(ref field, value, updateAction, propertyNames);
            }
            finally
            {
                if (!UndoRedoService.UndoRedoInProgress && createTransaction)
                {

View on GitHub (pinned to 96fad776d2)