{"record":{"id":"136a601aac37c4f4","repo":"stride3d/stride","slug":"setdescriptor-should-not-call-function-insert","errorCode":null,"errorMessage":"SetDescriptor should not call function 'Insert'.","messagePattern":"SetDescriptor should not call function 'Insert'\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"sources/core/Stride.Core.Reflection/TypeDescriptors/SetDescriptor.cs","lineNumber":92,"sourceCode":"    {\n        return thisObject is null || isReadOnlyMethod.Invoke(thisObject);\n    }\n\n    /// <summary>\n    /// Adds a value to a set.\n    /// </summary>\n    /// <param name=\"set\">The set.</param>\n    /// <param name=\"item\">The item.</param>\n    /// <exception cref=\"System.InvalidOperationException\">No Add() method found on set [{0}].ToFormat(Type)</exception>\n    public override void Add(object set, object? item)\n    {\n        ArgumentNullException.ThrowIfNull(set);\n        addMethod.Invoke(set, item);\n    }\n\n    public override void Insert(object set, int index, object? value)\n    {\n        throw new InvalidOperationException(\"SetDescriptor should not call function 'Insert'.\");\n    }\n\n    /// <summary>\n    /// Remove a value from a set\n    /// </summary>\n    /// <param name=\"set\">The set.</param>\n    /// <param name=\"key\">The key.</param>\n    public override void Remove(object set, object? key)\n    {\n        ArgumentNullException.ThrowIfNull(set);\n        removeMethod.Invoke(set, key);\n    }\n\n    public override void RemoveAt(object set, int index)\n    {\n        throw new InvalidOperationException($\"{nameof(SetDescriptor)} should not call function 'RemoveAt'.\");\n    }\n","sourceCodeStart":74,"sourceCodeEnd":110,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/core/Stride.Core.Reflection/TypeDescriptors/SetDescriptor.cs#L74-L110","documentation":"SetDescriptor is a type descriptor for set-like collections (e.g. HashSet). Sets are unordered, so index-based mutation via Insert is not supported; the base CollectionDescriptor API contract is intentionally violated to fail fast. If code reaches this path it treats a set as an ordered list, which is a bug in the caller.","triggerScenarios":"Calling SetDescriptor.Insert(set, index, value) directly, or generic code that iterates collection descriptors and calls Insert on every element type without checking it is an indexed list.","commonSituations":"Generic serialization/deserialization or data-binding code written for ListDescriptor re-used against a set descriptor; reflection-based editors attempting positional edits on HashSet<T> properties.","solutions":["Use the Add(object set, object item) method instead of Insert for sets","Check the descriptor type (e.g. descriptor is SetDescriptor) before calling index-based APIs","If ordered semantics are needed, change the property type from a set to IList<T>"],"exampleFix":"// before\ndescriptor.Insert(mySet, 0, newItem);\n// after\ndescriptor.Add(mySet, newItem);","handlingStrategy":"validation","validationCode":"if (descriptor is SetDescriptor)\n    descriptor.Add(set, item);\nelse\n    descriptor.Insert(set, index, item);","typeGuard":"bool IsSetDescriptor(object d) => d is SetDescriptor;","tryCatchPattern":null,"preventionTips":["Never call index-based collection APIs on set descriptors","Branch on descriptor type before positional operations","Prefer Add/Remove over Insert/RemoveAt for unordered collections"],"tags":["reflection","unsupported-operation","sets"],"backgroundTag":"unsupported-operation","analyzedSha":"96fad776d210c221682aac1ccdf4c79dc046fc38","analyzedAt":"2026-09-14T02:59:31.279Z","contentChangedAt":"2026-09-14T02:59:31.279Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}