{"record":{"id":"fb27adcc97297817","repo":"Cysharp/UniTask","slug":"disposable-is-already-set","errorCode":null,"errorMessage":"Disposable is already set","messagePattern":"Disposable is already set","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/UniTask/Assets/Plugins/UniTask/Runtime/UniTaskObservableExtensions.cs","lineNumber":341,"sourceCode":"                bool alreadyDisposed;\n                lock (gate)\n                {\n                    alreadyDisposed = disposed;\n                    old = current;\n                    if (!alreadyDisposed)\n                    {\n                        if (value == null) return;\n                        current = value;\n                    }\n                }\n\n                if (alreadyDisposed && value != null)\n                {\n                    value.Dispose();\n                    return;\n                }\n\n                if (old != null) throw new InvalidOperationException(\"Disposable is already set\");\n            }\n        }\n\n\n        public void Dispose()\n        {\n            IDisposable old = null;\n\n            lock (gate)\n            {\n                if (!disposed)\n                {\n                    disposed = true;\n                    old = current;\n                    current = null;\n                }\n            }\n","sourceCodeStart":323,"sourceCodeEnd":359,"githubUrl":"https://github.com/Cysharp/UniTask/blob/ceac8d6946b1125fe782cd171fbcb245b567dbf9/src/UniTask/Assets/Plugins/UniTask/Runtime/UniTaskObservableExtensions.cs#L323-L359","documentation":"Thrown by SingleAssignmentDisposable.Disposable setter when a non-null disposable is already assigned and a different non-null value is set. SingleAssignmentDisposable is designed to hold exactly one disposable; assigning a second one before Dispose is a programming error indicating a logic bug. The old disposable is not auto-disposed — the throw is intentional to surface the misuse.","triggerScenarios":"Setting the Disposable property twice on the same SingleAssignmentDisposable instance before calling Dispose. For example, subscribing twice and assigning each subscription to the same SingleAssignmentDisposable.","commonSituations":"Rx/Observable interop where multiple subscriptions reuse the same disposable holder. Event handler registration loops that overwrite the disposable. Refactoring that accidentally merges two subscription lifecycles into one SingleAssignmentDisposable.","solutions":["Use SerialAssignmentDisposable (or dispose the old one first) if you need to swap disposables","Call Dispose() on the SingleAssignmentDisposable before assigning a new value","Use a separate SingleAssignmentDisposable for each subscription","Null-check and dispose: if (holder.Disposable != null) holder.Disposable.Dispose(); before reassigning — but prefer SerialDisposable for this pattern"],"exampleFix":"// before\nvar sad = new SingleAssignmentDisposable();\nsad.Disposable = obs1.Subscribe(handler);\nsad.Disposable = obs2.Subscribe(handler); // throws\n\n// after (use SerialDisposable for swapping)\nvar sd = new SerialDisposable();\nsd.Disposable = obs1.Subscribe(handler);\nsd.Disposable = obs2.Subscribe(handler); // disposes obs1, ok","handlingStrategy":"validation","validationCode":"// Before assigning, check if already set\nif (holder.Disposable != null)\n{\n    holder.Disposable.Dispose(); // or use SerialDisposable instead\n}\nholder.Disposable = newSubscription;","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use SerialDisposable instead of SingleAssignmentDisposable when you need to swap subscriptions","Call Dispose() before reassigning if reusing a SingleAssignmentDisposable is truly needed","Create a new SingleAssignmentDisposable for each subscription lifecycle","Audit Rx subscription code for shared disposable holders during refactoring"],"tags":["unitask","observable","disposable","rx-interop","unity","csharp"],"backgroundTag":null,"analyzedSha":"ceac8d6946b1125fe782cd171fbcb245b567dbf9","analyzedAt":"2026-08-13T19:16:39.025Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}