{"record":{"id":"b8334eb3ed7675de","repo":"AvaloniaUI/Avalonia","slug":"property-name-doesn-t-have-a-getter","errorCode":null,"errorMessage":"Property {Name} doesn't have a getter","messagePattern":"Property (.+?) doesn't have a getter","errorType":"exception","errorClass":"NotSupportedException","httpStatus":null,"severity":"error","filePath":"src/Avalonia.Base/Data/Core/ClrPropertyInfo.cs","lineNumber":25,"sourceCode":"    {\n        private readonly Func<object, object?>? _getter;\n        private readonly Action<object, object?>? _setter;\n\n        public ClrPropertyInfo(string name, Func<object, object?>? getter, Action<object, object?>? setter, Type propertyType)\n        {\n            _getter = getter;\n            _setter = setter;\n            PropertyType = propertyType;\n            Name = name;\n        }\n\n        public string Name { get; }\n        public Type PropertyType { get; }\n\n        public object? Get(object target)\n        {\n            if (_getter == null)\n                throw new NotSupportedException(\"Property \" + Name + \" doesn't have a getter\");\n            return _getter(target);\n        }\n\n        public void Set(object target, object? value)\n        {\n            if (_setter == null)\n                throw new NotSupportedException(\"Property \" + Name + \" doesn't have a setter\");\n            _setter(target, value);\n        }\n\n        public bool CanSet => _setter != null;\n        public bool CanGet => _getter != null;\n    }\n\n    public class ReflectionClrPropertyInfo : ClrPropertyInfo\n    {\n        private static Action<object, object?>? CreateSetter(PropertyInfo info)\n            => info.SetMethod is { } setMethod ?","sourceCodeStart":7,"sourceCodeEnd":43,"githubUrl":"https://github.com/AvaloniaUI/Avalonia/blob/11c542726898ae954a1ef668c65ec79ec92ab17d/src/Avalonia.Base/Data/Core/ClrPropertyInfo.cs#L7-L43","documentation":"ClrPropertyInfo wraps a CLR property's getter and setter delegates. Get() throws NotSupportedException when the property was constructed with a null getter, i.e. the property is write-only (set accessor only). Avalonia binds by reading the property, so a write-only property cannot supply a value.","triggerScenarios":"Binding (reading direction) to a CLR property that only has a setter. Occurs when reflection or an explicit ClrPropertyInfo is created from a write-only member and then the binding engine calls Get().","commonSituations":"Binding a control to a viewmodel property declared as `public int X { set; }`; password-style write-only fields; refactoring a property to remove its getter while a binding still targets it.","solutions":["Add a getter to the bound property (`public int X { get; set; }`).","Repoint the binding to a different property that is readable.","If using OneWayToSource only, ensure the binding direction is actually source-bound and you never read the target property."],"exampleFix":"// before\npublic string Secret { set; }\n<TextBlock Text=\"{Binding Secret}\" />\n// after\npublic string Secret { get; set; }","handlingStrategy":"type-guard","validationCode":"// Check CanGet before reading via ClrPropertyInfo.\nif (propertyInfo is ClrPropertyInfo clr && !clr.CanGet)\n    throw new InvalidOperationException($\"{clr.Name} is write-only and cannot be read.\");\nvar value = propertyInfo.Get(target);","typeGuard":"static bool IsReadable(ClrPropertyInfo p) => p.CanGet;","tryCatchPattern":"try { return propertyInfo.Get(target); }\ncatch (NotSupportedException) { /* property has no getter */ return AvaloniaProperty.UnsetValue; }","preventionTips":["Prefer get/set auto-properties for bindable viewmodel members.","When reflecting, filter out write-only members before binding.","Keep a test binding each read-only-vs-write-only path."],"tags":["data-binding","reflection","clr-property","read-only"],"backgroundTag":null,"analyzedSha":"11c542726898ae954a1ef668c65ec79ec92ab17d","analyzedAt":"2026-08-13T11:57:40.261Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}