{"record":{"id":"1db79314677da11d","repo":"dotnet/reactive","slug":"strings-core-disposable-already-assigned","errorCode":null,"errorMessage":"Strings_Core.DISPOSABLE_ALREADY_ASSIGNED","messagePattern":"Strings_Core\\.DISPOSABLE_ALREADY_ASSIGNED","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"Rx.NET/Source/src/System.Reactive/Disposables/SingleAssignmentDisposableValue.cs","lineNumber":39,"sourceCode":"            // We use a sentinel value to indicate we've been disposed. This sentinel never leaks\n            // to the outside world (see the Disposable property getter), so no-one can ever assign\n            // this value to us manually.\n            Volatile.Read(ref _current) == BooleanDisposable.True;\n\n        /// <summary>\n        /// Gets or sets the underlying disposable. After disposal, the result of getting this property is undefined.\n        /// </summary>\n        /// <exception cref=\"InvalidOperationException\">Thrown if the <see cref=\"SingleAssignmentDisposable\"/> has already been assigned to.</exception>\n        public IDisposable? Disposable\n        {\n            get => Disposables.Disposable.GetValueOrDefault(ref _current);\n            set\n            {\n                var result = Disposables.Disposable.TrySetSingle(ref _current, value);\n\n                if (result == TrySetSingleResult.AlreadyAssigned)\n                {\n                    throw new InvalidOperationException(Strings_Core.DISPOSABLE_ALREADY_ASSIGNED);\n                }\n            }\n        }\n\n        /// <summary>\n        /// Disposes the underlying disposable.\n        /// </summary>\n        public void Dispose()\n        {\n            Disposables.Disposable.Dispose(ref _current);\n        }\n\n        /// <inheritdoc/>\n        public override readonly bool Equals(object? obj) => false;\n\n        /// <inheritdoc/>\n        public override readonly int GetHashCode() => 0;\n","sourceCodeStart":21,"sourceCodeEnd":57,"githubUrl":"https://github.com/dotnet/reactive/blob/94b5d5ab912789f5abe9a72138a25bbd716fe59c/Rx.NET/Source/src/System.Reactive/Disposables/SingleAssignmentDisposableValue.cs#L21-L57","documentation":"SingleAssignmentDisposableValue.Disposable may be assigned only once; a second assignment raises InvalidOperationException with the DISPOSABLE_ALREADY_ASSIGNED message. This enforces the single-assignment contract that lets the class safely swap-free storage of one disposable.","triggerScenarios":"Setting the Disposable property a second time with a different value after an initial assignment — e.g. re-using a SingleAssignmentDisposableValue field for a second subscription or re-running an initialization path.","commonSituations":"Re-subscribing with the same field without recreating the wrapper, event handlers firing initialization twice, retry loops that assign a new disposable into the same field, or accidental shared instances between two call sites.","solutions":["Create a new SingleAssignmentDisposableValue for each assignment instead of reusing one.","Check whether it is already assigned (e.g. keep a flag or use TrySetSingle semantics) before setting.","Switch to SerialDisposable, which allows the inner disposable to be replaced repeatedly."],"exampleFix":"// before\nsubscription.Disposable = newDisposable; // second assignment -> throws\n// after\nsubscription = new SingleAssignmentDisposableValue { Disposable = newDisposable };","handlingStrategy":"type-guard","validationCode":"// Only assign once per instance; recreate for new subscriptions\nsubscription = new SingleAssignmentDisposableValue { Disposable = d };","typeGuard":"static bool CanAssign(SingleAssignmentDisposableValue s, IDisposable newValue) => true; // no public read; guard by design: never reassign","tryCatchPattern":"try { sabv.Disposable = d; }\ncatch (InvalidOperationException) { /* already assigned: create a new instance or ignore duplicate assign */ }","preventionTips":["Use SerialDisposable when the inner disposable must be replaceable.","Never reuse a SingleAssignmentDisposableValue across subscriptions; allocate per assignment.","Guard initialization paths against double execution (e.g. Interlocked flags)."],"tags":["invalid-operation","disposables","single-assignment","system-reactive"],"backgroundTag":"invalid-state-transition","analyzedSha":"94b5d5ab912789f5abe9a72138a25bbd716fe59c","analyzedAt":"2026-09-15T02:26:24.759Z","contentChangedAt":"2026-09-15T02:26:24.759Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}