{"record":{"id":"551886d4ff2f8e25","repo":"AvaloniaUI/Avalonia","slug":"value-cannot-be-null-parameter-tcs","errorCode":null,"errorMessage":"Value cannot be null. (Parameter 'tcs')","messagePattern":"Value cannot be null\\. \\(Parameter 'tcs'\\)","errorType":"exception","errorClass":"ArgumentNullException","httpStatus":null,"severity":"error","filePath":"src/Avalonia.Base/Reactive/AnonymousObserver.cs","lineNumber":21,"sourceCode":"using static Avalonia.Reactive.AnonymousObserverNonGenericHelper;\n\nnamespace Avalonia.Reactive;\n\n/// <summary>\n/// Class to create an <see cref=\"IObserver{T}\"/> instance from delegate-based implementations of the On* methods.\n/// </summary>\n/// <typeparam name=\"T\">The type of the elements in the sequence.</typeparam>\npublic class AnonymousObserver<T> : IObserver<T>\n{\n    private readonly Action<T> _onNext;\n    private readonly Action<Exception> _onError;\n    private readonly Action _onCompleted;\n\n    public AnonymousObserver(TaskCompletionSource<T> tcs)\n    {\n        if (tcs is null)\n        {\n            throw new ArgumentNullException(nameof(tcs));\n        }\n\n        _onNext = tcs.SetResult;\n        _onError = tcs.SetException;\n        _onCompleted = NoOpCompleted;\n    }\n    \n    public AnonymousObserver(Action<T> onNext, Action<Exception> onError, Action onCompleted)\n    {\n        _onNext = onNext ?? throw new ArgumentNullException(nameof(onNext));\n        _onError = onError ?? throw new ArgumentNullException(nameof(onError));\n        _onCompleted = onCompleted ?? throw new ArgumentNullException(nameof(onCompleted));\n    }\n\n    public AnonymousObserver(Action<T> onNext)\n        : this(onNext, ThrowsOnError, NoOpCompleted)\n    {\n    }","sourceCodeStart":3,"sourceCodeEnd":39,"githubUrl":"https://github.com/AvaloniaUI/Avalonia/blob/11c542726898ae954a1ef668c65ec79ec92ab17d/src/Avalonia.Base/Reactive/AnonymousObserver.cs#L3-L39","documentation":"AnonymousObserver<T> has a constructor that adapts a TaskCompletionSource<T> into an IObserver<T> (OnNext=SetResult, OnError=SetException, OnCompleted=NoOp). It throws ArgumentNullException(nameof(tcs)) when tcs is null, because adapting a null TCS would later NullRef inside the observer callbacks. Fail-fast at construction.","triggerScenarios":"Constructing new AnonymousObserver<T>(null) by passing a TaskCompletionSource variable that is null, then subscribing it to an IObservable<T>.","commonSituations":"Bridge code that subscribes an observer built from a TCS where the TCS was never initialized or was cleared after use, often in async-over-reactive adapters.","solutions":["Ensure the TaskCompletionSource<T> is constructed (new TaskCompletionSource<T>()) before passing it.","Null-check at the call site if the TCS comes from an optional/computed source and skip the subscription when null.","Prefer Observable.ToTask / FirstAsync extensions over hand-rolled TCS-to-observer adapters where available."],"exampleFix":"// before\nvar tcs = GetMaybeNullTcs();\nsource.Subscribe(new AnonymousObserver<T>(tcs)); // throws if null\n\n// after\nvar tcs = new TaskCompletionSource<T>();\nsource.Subscribe(new AnonymousObserver<T>(tcs));\nreturn tcs.Task;","handlingStrategy":"validation","validationCode":"if (tcs is null) throw new InvalidOperationException(\"TCS required\");\nsource.Subscribe(new AnonymousObserver<T>(tcs));","typeGuard":"bool HasTcs<T>(TaskCompletionSource<T>? tcs) => tcs is not null;","tryCatchPattern":null,"preventionTips":["Always construct the TaskCompletionSource<T> before adapting it.","Prefer framework ToTask/FirstAsync over hand-rolled TCS adapters.","Null-check TCS fields from optional sources before subscribing."],"tags":["avalonia","reactive","observer","argumentnull","tcs"],"backgroundTag":null,"analyzedSha":"11c542726898ae954a1ef668c65ec79ec92ab17d","analyzedAt":"2026-08-13T11:57:40.261Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}