{"record":{"id":"21c729354df7b60a","repo":"dotnet/reactive","slug":"value-cannot-be-null-parameter-type","errorCode":null,"errorMessage":"Value cannot be null. (Parameter 'type')","messagePattern":"Value cannot be null\\. \\(Parameter 'type'\\)","errorType":"validation","errorClass":"ArgumentNullException","httpStatus":null,"severity":"error","filePath":"Rx.NET/Source/src/System.Reactive/Linq/Observable.Events.cs","lineNumber":859,"sourceCode":"        /// <para>\n        /// If no SynchronizationContext is present at the point of calling FromEventPattern, add and remove handler invocations are made synchronously on the thread\n        /// making the Subscribe or Dispose call, respectively.\n        /// </para>\n        /// <para>\n        /// It's recommended to lift FromEventPattern calls outside event stream query expressions due to the free-threaded nature of Reactive Extensions. Doing so\n        /// makes the captured SynchronizationContext predictable. This best practice also reduces clutter of bridging code inside queries, making the query expressions\n        /// more concise and easier to understand.\n        /// </para>\n        /// </remarks>\n        /// <seealso cref=\"ToEventPattern\"/>\n#if HAS_TRIMMABILITY_ATTRIBUTES\n        [RequiresUnreferencedCode(Constants_Core.EventReflectionTrimIncompatibilityMessage)]\n#endif\n        public static IObservable<EventPattern<object>> FromEventPattern(Type type, string eventName)\n        {\n            if (type == null)\n            {\n                throw new ArgumentNullException(nameof(type));\n            }\n\n            if (eventName == null)\n            {\n                throw new ArgumentNullException(nameof(eventName));\n            }\n\n            return s_impl.FromEventPattern(type, eventName);\n        }\n\n        /// <summary>\n        /// Converts a static .NET event, conforming to the standard .NET event pattern with an <see cref=\"EventArgs\"/> parameter, to an observable sequence.\n        /// Each event invocation is surfaced through an OnNext message in the resulting sequence.\n        /// Reflection is used to discover the event based on the specified type and the specified event name.\n        /// For conversion of events that don't conform to the standard .NET event pattern, use any of the FromEvent overloads instead.\n        /// </summary>\n        /// <param name=\"type\">Type that exposes the static event to convert.</param>\n        /// <param name=\"eventName\">Name of the event to convert.</param>","sourceCodeStart":841,"sourceCodeEnd":877,"githubUrl":"https://github.com/dotnet/reactive/blob/94b5d5ab912789f5abe9a72138a25bbd716fe59c/Rx.NET/Source/src/System.Reactive/Linq/Observable.Events.cs#L841-L877","documentation":"The static-event overload FromEventPattern(Type type, string eventName) reflects over the given Type to find a static event. A null Type gives reflection no target, so Rx throws ArgumentNullException eagerly at the public API boundary rather than failing inside reflection.","triggerScenarios":"Calling Observable.FromEventPattern((Type)null, eventName) — the Type came from typeof on a missing generic argument, Assembly.GetType returning null for an unknown type name, or a Type variable not yet assigned.","commonSituations":"Reflection-based plugin loading where Assembly.GetType(name) returns null because the type name is wrong or the assembly isn't loaded; generics where typeof(T) is replaced by a nullable Type variable; config-driven static event subscription with a bad type name.","solutions":["Use typeof(SomeClass) directly for the static event's declaring type so the compiler verifies it.","If the Type comes from a string, check Type.GetType/Assembly.GetType result for null before calling and throw a descriptive error.","Load the required assembly before resolving the Type by name."],"exampleFix":"// before\nvar t = asm.GetType(config.TypeName); // null if name is wrong\nvar obs = Observable.FromEventPattern(t, config.EventName);\n// after\nvar t = asm.GetType(config.TypeName) ?? throw new InvalidOperationException($\"Type {config.TypeName} not found\");\nvar obs = Observable.FromEventPattern(t, config.EventName);","handlingStrategy":"validation","validationCode":"if (type is null) throw new InvalidOperationException($\"Type '{typeName}' could not be resolved for static event subscription\");\nvar obs = Observable.FromEventPattern(type, eventName);","typeGuard":"static bool IsValidStaticEvent(Type type, string eventName) =>\n    type != null && type.GetEvent(eventName, BindingFlags.Static | BindingFlags.Public) != null;","tryCatchPattern":"try\n{\n    var obs = Observable.FromEventPattern(type, eventName);\n}\ncatch (ArgumentNullException ex) when (ex.ParamName == \"type\")\n{\n    // log that the type resolution failed; skip or rethrow with type name\n}","preventionTips":["Use typeof(T) directly instead of Type variables resolved from strings.","Null-check Assembly.GetType results before use.","Ensure required assemblies are loaded before resolving types by name."],"tags":["csharp","rx","argument-null","reflection","static-events"],"backgroundTag":"null-argument","analyzedSha":"94b5d5ab912789f5abe9a72138a25bbd716fe59c","analyzedAt":"2026-09-15T02:26:24.759Z","contentChangedAt":"2026-09-15T02:26:24.759Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}