stride3d/stride · error · InvalidOperationException

SetObject can only be used for Permutation or Object keys

Error message

SetObject can only be used for Permutation or Object keys

What it means

SetObject only accepts keys whose ParameterKeyType is Permutation or Object because only those types are backed by the ObjectValues reference array. Calling it with a typed key (e.g. a float or texture key) would corrupt typed storage, so it throws InvalidOperationException.

Solutions

  1. Use the typed Set<T> API for the key's actual type
  2. Only call SetObject with keys whose Type is ParameterKeyType.Permutation or ParameterKeyType.Object
  3. Check key.Type before dispatching to SetObject vs Set

Example fix

// before
collection.SetObject(TextureKey, myTexture); // typed key
// after
collection.Set(TextureKey, myTexture);
Defensive patterns

Strategy: validation

Validate before calling

if (key.Type is not (ParameterKeyType.Permutation or ParameterKeyType.Object))
    throw new ArgumentException("SetObject requires Permutation or Object keys");
collection.SetObject(key, value);

Type guard

bool IsObjectKey(ParameterKey key) => key.Type is ParameterKeyType.Permutation or ParameterKeyType.Object;

Try / catch

try { collection.SetObject(key, value); } catch (InvalidOperationException ex) { /* fall back to typed Set<T> */ }

Prevention

When it happens

Trigger: Calling SetObject with a ParameterKey declared as a value/typed key (key.Type is neither Permutation nor Object).

Common situations: Generic helper code that routes all parameter writes through SetObject; refactored key whose type changed; copying parameters between collections with a generic API.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

Thrown at sources/engine/Stride.Foundation/Rendering/ParameterCollection.cs:497

        {
            return (T)ObjectValues[parameter.BindingSlot];
        }

        /// <summary>
        /// Gets an object.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="parameterAccessor"></param>
        /// <returns></returns>
        public T Get<T>(ObjectParameterAccessor<T> parameterAccessor)
        {
            return (T)ObjectValues[parameterAccessor.BindingSlot];
        }

        public void SetObject(ParameterKey key, object value)
        {
            if (key.Type != ParameterKeyType.Permutation && key.Type != ParameterKeyType.Object)
                throw new InvalidOperationException("SetObject can only be used for Permutation or Object keys");

            var accessor = GetObjectParameterHelper(key);
            if (key.Type == ParameterKeyType.Permutation)
            {
                var oldValue = ObjectValues[accessor.Offset];
                if ((oldValue != null && (value == null || !oldValue.Equals(value))) // oldValue non null => check equality
                    || (oldValue == null && value != null)) // oldValue null => check if value too
                        PermutationCounter++;
            }
            ObjectValues[accessor.Offset] = value;
        }

        public object GetObject(ParameterKey key)
        {
            if (key.Type != ParameterKeyType.Permutation && key.Type != ParameterKeyType.Object)
                throw new InvalidOperationException("GetObject can only be used for Permutation or Object keys");

            var accessor = GetObjectParameterHelper(key, false);

View on GitHub (pinned to 96fad776d2)