{"record":{"id":"176f758316dcd098","repo":"SignalR/SignalR","slug":"ondata","errorCode":null,"errorMessage":"onData","messagePattern":"onData","errorType":"validation","errorClass":"ArgumentNullException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.AspNet.SignalR.Client/HubProxyExtensions.cs","lineNumber":63,"sourceCode":"        /// <param name=\"proxy\">The <see cref=\"IHubProxy\"/>.</param>\n        /// <param name=\"eventName\">The name of the event.</param>\n        /// <param name=\"onData\">The callback</param>\n        /// <returns>An <see cref=\"IDisposable\"/> that represents this subscription.</returns>\n        public static IDisposable On(this IHubProxy proxy, string eventName, Action onData)\n        {\n            if (proxy == null)\n            {\n                throw new ArgumentNullException(\"proxy\");\n            }\n\n            if (String.IsNullOrEmpty(eventName))\n            {\n                throw new ArgumentNullException(\"eventName\");\n            }\n\n            if (onData == null)\n            {\n                throw new ArgumentNullException(\"onData\");\n            }\n\n            Subscription subscription = proxy.Subscribe(eventName);\n\n            Action<IList<JToken>> handler = args =>\n            {\n                ExecuteCallback(eventName, args.Count, 0, onData);\n            };\n\n            subscription.Received += handler;\n\n            return new DisposableAction(() => subscription.Received -= handler);\n        }\n\n        /// <summary>\n        /// Registers for an event with the specified name and callback\n        /// </summary>\n        /// <param name=\"proxy\">The <see cref=\"IHubProxy\"/>.</param>","sourceCodeStart":45,"sourceCodeEnd":81,"githubUrl":"https://github.com/SignalR/SignalR/blob/693053b89a9e1f5ce819e3233ed159a6409de22b/src/Microsoft.AspNet.SignalR.Client/HubProxyExtensions.cs#L45-L81","documentation":"HubProxyExtensions.On throws ArgumentNullException('onData') when the callback Action is null. The subscription wraps onData and invokes it per event payload, so a null handler is meaningless and would NRE later — the guard fails fast.","triggerScenarios":"Passing null as the callback; handler resolved from a factory that returned null; conditional handler assignment that skipped the real lambda.","commonSituations":"Refactor left the handler unassigned; DI/factory returned null; copy-paste dropped the lambda body.","solutions":["Always pass a concrete Action; use () => { } as a no-op if you only need side-effect-free subscription.","If the handler comes from a factory, validate it is non-null before subscribing.","Prefer method-group references over nullable delegate fields."],"exampleFix":"// before\nproxy.On(\"ping\", null);\n// after\nproxy.On(\"ping\", () => HandlePing());","handlingStrategy":"validation","validationCode":"if (onData == null) throw new ArgumentNullException(nameof(onData));\nproxy.On(eventName, onData);","typeGuard":"static bool HasHandler(Action h) => h != null;","tryCatchPattern":null,"preventionTips":["Always pass a concrete Action; use () => { } as an explicit no-op.","Validate factory-produced handlers before subscribing.","Prefer method-group references over nullable delegate fields."],"tags":["signalr","hub-proxy","argument-validation","null-check","callback","event-subscription"],"backgroundTag":null,"analyzedSha":"693053b89a9e1f5ce819e3233ed159a6409de22b","analyzedAt":"2026-08-13T22:23:59.793Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}