{"record":{"id":"0ca3b339b4527e24","repo":"stride3d/stride","slug":"class-type-is-expected","errorCode":null,"errorMessage":"Class type is expected.","messagePattern":"Class type is expected\\.","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"sources/core/Stride.Core/PropertyContainer.cs","lineNumber":527,"sourceCode":"                PropertyUpdated?.Invoke(ref this, propertyKey, tagValue, previousValue);\n                propertyKey.PropertyUpdateCallback?.Invoke(ref this, propertyKey, tagValue, previousValue);\n            }\n        }\n        else\n        {\n            if (tryToAdd)\n                properties.Add(propertyKey, valueToSet);\n            else\n                properties[propertyKey] = valueToSet;\n        }\n\n        propertyKey.ObjectInvalidationMetadata?.Invalidate(Owner, propertyKey, oldValue);\n    }\n\n    public static void AddAccessorProperty(Type type, PropertyKey propertyKey)\n    {\n        if (!type.GetTypeInfo().IsClass)\n            throw new ArgumentException(\"Class type is expected.\", nameof(type));\n\n        if (propertyKey.AccessorMetadata == null)\n            throw new ArgumentException(\"Given PropertyKey doesn't have accessor metadata.\", nameof(propertyKey));\n\n        if (!AccessorProperties.TryGetValue(type, out var typeAccessorProperties))\n            AccessorProperties.Add(type, typeAccessorProperties = []);\n\n        typeAccessorProperties.Add(propertyKey);\n    }\n\n    internal void RaisePropertyContainerUpdated(PropertyKey propertyKey, object newValue, object oldValue)\n    {\n        PropertyUpdated?.Invoke(ref this, propertyKey, newValue, oldValue);\n    }\n\n    private object? GetNonRecursive(PropertyKey propertyKey)\n    {\n        // Get bound value, if any.","sourceCodeStart":509,"sourceCodeEnd":545,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/core/Stride.Core/PropertyContainer.cs#L509-L545","documentation":"PropertyContainer.AddAccessorProperty registers a PropertyKey as an accessor property for a type, and the registry is keyed by Type with the assumption it maps to class instances. Passing a struct, enum, interface, or other non-class Type throws ArgumentException because accessor semantics only apply to class types.","triggerScenarios":"Calling PropertyContainer.AddAccessorProperty(typeof(SomeStruct) or an interface, somePropertyKey) where the type's TypeInfo.IsClass is false.","commonSituations":"Registering accessor properties for value-type models or interfaces; generic helper code that forwards typeof(T) where T is unconstrained and instantiated with a struct.","solutions":["Pass the concrete class type that owns the property.","Constrain generic helper methods with `where T : class`.","If the type is a struct by design, do not use accessor-property registration for it."],"exampleFix":"// before\nPropertyContainer.AddAccessorProperty(typeof(MyPoint), PositionKey); // struct\n// after\nPropertyContainer.AddAccessorProperty(typeof(MyEntity), PositionKey); // class","handlingStrategy":"type-guard","validationCode":"if (!type.GetTypeInfo().IsClass)\n    throw new InvalidOperationException(\"AddAccessorProperty requires a class type\");","typeGuard":"static bool IsClass(Type t) => t.GetTypeInfo().IsClass;","tryCatchPattern":"try { PropertyContainer.AddAccessorProperty(type, key); }\ncatch (ArgumentException ex) when (ex.Message == \"Class type is expected.\")\n{\n    // caller passed a struct/interface; skip or resolve the concrete class\n}","preventionTips":["Constrain generics to `where T : class` before calling AddAccessorProperty.","Resolve interfaces to their concrete implementation class before registering.","Only register accessor properties for class-based entities/components."],"tags":["argument-exception","type-mismatch","property-system"],"backgroundTag":"type-mismatch","analyzedSha":"96fad776d210c221682aac1ccdf4c79dc046fc38","analyzedAt":"2026-09-14T02:59:31.279Z","contentChangedAt":"2026-09-14T02:59:31.279Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}