{"record":{"id":"0360e438244170c6","repo":"HangfireIO/Hangfire","slug":"dispatcher","errorCode":null,"errorMessage":"dispatcher","messagePattern":"dispatcher","errorType":"validation","errorClass":"ArgumentNullException","httpStatus":null,"severity":"error","filePath":"src/Hangfire.Core/Obsolete/RequestDispatcherWrapper.cs","lineNumber":30,"sourceCode":"// \n// You should have received a copy of the GNU Lesser General Public \n// License along with Hangfire. If not, see <http://www.gnu.org/licenses/>.\n\nusing System;\nusing System.Threading.Tasks;\nusing Hangfire.Annotations;\n\n// ReSharper disable once CheckNamespace\nnamespace Hangfire.Dashboard\n{\n    [Obsolete(\"Use IDashboardDispatcher-based dispatchers instead. Will be removed in 2.0.0.\")]\n    public class RequestDispatcherWrapper : IDashboardDispatcher\n    {\n        private readonly IRequestDispatcher _dispatcher;\n        \n        public RequestDispatcherWrapper([NotNull] IRequestDispatcher dispatcher)\n        {\n            if (dispatcher == null) throw new ArgumentNullException(nameof(dispatcher));\n            _dispatcher = dispatcher;\n        }\n\n        public Task Dispatch(DashboardContext context)\n        {\n            return _dispatcher.Dispatch(RequestDispatcherContext.FromDashboardContext(context));\n        }\n    }\n}","sourceCodeStart":12,"sourceCodeEnd":39,"githubUrl":"https://github.com/HangfireIO/Hangfire/blob/c236dd0f930f831ec151e436e138ddc429a02a72/src/Hangfire.Core/Obsolete/RequestDispatcherWrapper.cs#L12-L39","documentation":"Thrown as ArgumentNullException by the obsolete RequestDispatcherWrapper constructor when the 'dispatcher' IRequestDispatcher argument is null. The wrapper adapts a legacy IRequestDispatcher to the modern IDashboardDispatcher interface by delegating Dispatch; a null inner dispatcher has nothing to delegate to, so the constructor rejects it at line 30.","triggerScenarios":"Constructing 'new RequestDispatcherWrapper(null)' — i.e. wrapping a null IRequestDispatcher, typically because the dispatcher instance was never created, failed to resolve from a factory, or was lost in a refactor.","commonSituations":"Custom dashboard route registration that wraps legacy dispatchers but passes null due to a factory returning null; migration from IRequestDispatcher to IDashboardDispatcher where the adapter is constructed before the adaptee exists; tests that stub the wrapper without a real dispatcher.","solutions":["Migrate your dispatcher to implement IDashboardDispatcher directly and register it without the obsolete wrapper.","If you must use the wrapper, ensure the IRequestDispatcher instance is constructed and non-null before wrapping (guard the factory result).","Register routes with a non-null dispatcher: routes.Add(path, new RequestDispatcherWrapper(myDispatcher))."],"exampleFix":"// before\nroutes.Add(\"/jobs\", new RequestDispatcherWrapper(null));\n\n// after\nroutes.Add(\"/jobs\", new MyModernDispatcher()); // implements IDashboardDispatcher","handlingStrategy":"validation","validationCode":"if (dispatcher == null) throw new ArgumentNullException(nameof(dispatcher));\nroutes.Add(\"/path\", new RequestDispatcherWrapper(dispatcher));","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Migrate dispatchers to implement IDashboardDispatcher directly, dropping the wrapper.","Guard factory results before wrapping."],"tags":["argument-null","dashboard","dispatcher","obsolete","adapter"],"backgroundTag":null,"analyzedSha":"c236dd0f930f831ec151e436e138ddc429a02a72","analyzedAt":"2026-08-13T20:27:11.027Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}