{"record":{"id":"0bc8cc1fba03a203","repo":"AvaloniaUI/Avalonia","slug":"a-member-accessor-can-be-subscribed-to-only-once","errorCode":null,"errorMessage":"A member accessor can be subscribed to only once.","messagePattern":"A member accessor can be subscribed to only once\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Avalonia.Base/Data/Core/Plugins/PropertyAccessorBase.cs","lineNumber":37,"sourceCode":"        public void Dispose()\n        {\n            if (_listener != null)\n            {\n                Unsubscribe();\n            }\n        }\n\n        /// <inheritdoc/>\n        public abstract bool SetValue(object? value, BindingPriority priority);\n\n        /// <inheritdoc/>\n        public void Subscribe(Action<object?> listener)\n        {\n            _ = listener ?? throw new ArgumentNullException(nameof(listener));\n\n            if (_listener != null)\n            {\n                throw new InvalidOperationException(\n                    \"A member accessor can be subscribed to only once.\");\n            }\n\n            _listener = listener;\n            SubscribeCore();\n        }\n\n        public void Unsubscribe()\n        {\n            if (_listener == null)\n            {\n                throw new InvalidOperationException(\n                    \"The member accessor was not subscribed.\");\n            }\n\n            UnsubscribeCore();\n            _listener = null;\n        }","sourceCodeStart":19,"sourceCodeEnd":55,"githubUrl":"https://github.com/AvaloniaUI/Avalonia/blob/11c542726898ae954a1ef668c65ec79ec92ab17d/src/Avalonia.Base/Data/Core/Plugins/PropertyAccessorBase.cs#L19-L55","documentation":"PropertyAccessorBase enforces single-subscription semantics: Subscribe stores one listener and calls SubscribeCore. Calling Subscribe again while a listener is already set throws InvalidOperationException. The binding engine normally manages this; encountering it means a double subscription of the same accessor instance.","triggerScenarios":"Calling accessor.Subscribe(handler) twice without an intervening Unsubscribe; a custom binding or expression node that subscribes the same accessor twice; sharing one accessor between two consumers.","commonSituations":"Custom IPropertyAccessor consumers; reusing an accessor across two bindings; forgetting to Dispose/Unsubscribe before re-subscribing.","solutions":["Call Unsubscribe (or Dispose) before subscribing again.","Create a fresh accessor instance for each additional listener rather than reusing one.","Let the binding engine own Subscribe/Unsubscribe; do not subscribe manually."],"exampleFix":"// before\naccessor.Subscribe(handler1);\naccessor.Subscribe(handler2); // throws\n// after\naccessor.Dispose();\naccessor = factory.Create();\naccessor.Subscribe(handler2);","handlingStrategy":"validation","validationCode":"// Track subscription state and only subscribe once per accessor:\nif (_subscribed) { accessor.Dispose(); accessor = CreateAccessor(); }\naccessor.Subscribe(handler);\n_subscribed = true;","typeGuard":null,"tryCatchPattern":"try { accessor.Subscribe(handler); }\ncatch (InvalidOperationException) { /* dispose and recreate the accessor, then retry */ }","preventionTips":["Call Unsubscribe/Dispose before re-subscribing.","Create a fresh accessor for each additional listener.","Let the binding engine own subscription lifecycle."],"tags":["binding","accessor","subscription","lifecycle"],"backgroundTag":null,"analyzedSha":"11c542726898ae954a1ef668c65ec79ec92ab17d","analyzedAt":"2026-08-13T11:57:40.261Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}