{"record":{"id":"5d0ad44f1f221965","repo":"HangfireIO/Hangfire","slug":"parameters-passed-by-reference-are-not-supported","errorCode":null,"errorMessage":"Parameters, passed by reference, are not supported: there is no guarantee that specified method will be invoked inside the same process.","messagePattern":"Parameters, passed by reference, are not supported: there is no guarantee that specified method will be invoked inside the same process\\.","errorType":"exception","errorClass":"NotSupportedException","httpStatus":null,"severity":"error","filePath":"src/Hangfire.Core/Common/Job.cs","lineNumber":526,"sourceCode":"                    \"Argument count must be equal to method parameter count.\",\n                    argumentParameterName);\n            }\n\n            foreach (var parameter in parameters)\n            {\n                // There is no guarantee that specified method will be invoked\n                // in the same process. Therefore, output parameters and parameters\n                // passed by reference are not supported.\n\n                if (parameter.IsOut)\n                {\n                    throw new NotSupportedException(\n                        \"Output parameters are not supported: there is no guarantee that specified method will be invoked inside the same process.\");\n                }\n\n                if (parameter.ParameterType.IsByRef)\n                {\n                    throw new NotSupportedException(\n                        \"Parameters, passed by reference, are not supported: there is no guarantee that specified method will be invoked inside the same process.\");\n                }\n\n                var parameterTypeInfo = parameter.ParameterType.GetTypeInfo();\n                \n                if (parameterTypeInfo.IsSubclassOf(typeof(Delegate)) || parameterTypeInfo.IsSubclassOf(typeof(Expression)))\n                {\n                    throw new NotSupportedException(\n                        \"Anonymous functions, delegates and lambda expressions aren't supported in job method parameters: it's very hard to serialize them and all their scope in general.\");\n                }\n            }\n        }\n\n        private static object[] GetExpressionValues(ReadOnlyCollection<Expression> expressions)\n        {\n            var result = expressions.Count > 0 ? new object[expressions.Count] : [];\n            var index = 0;\n","sourceCodeStart":508,"sourceCodeEnd":544,"githubUrl":"https://github.com/HangfireIO/Hangfire/blob/c236dd0f930f831ec151e436e138ddc429a02a72/src/Hangfire.Core/Common/Job.cs#L508-L544","documentation":"NotSupportedException thrown by Job.Validate when a parameter's ParameterType.IsByRef is true — i.e., the method declares a 'ref' parameter. Like out parameters, ref parameters require bidirectional in-place mutation at the call site, which is impossible when the method runs in a different process and arguments are serialized copies. Hangfire rejects this at definition time to prevent silent data loss.","triggerScenarios":"Enqueuing () => service.Run(ref counter); a method declared as public void Run(ref int x); using methods that swap or mutate caller-provided values via ref.","commonSituations":"Wrapping methods designed for in-process computation (e.g., exchange-and-compare patterns) as jobs; refactoring to add a ref parameter; interop with APIs that use ref for performance.","solutions":["Remove the ref modifier; pass the value by value and return the updated value via the method's return type.","Wrap the ref-based method in a public method with plain parameters and enqueue the wrapper.","If mutation semantics are required, persist the value in storage keyed by job ID and read/write it inside the job body."],"exampleFix":"// before — ref parameter, unsupported\npublic class Worker {\n    public void Run(ref int counter) { counter++; }\n}\n\n// after — return the new value\npublic class Worker {\n    public int Run(int counter) { return counter + 1; }\n}\nBackgroundJob.Enqueue<Worker>(x => x.Run(0));","handlingStrategy":"validation","validationCode":"if (method.GetParameters().Any(p => p.ParameterType.IsByRef))\n    throw new NotSupportedException(\"Job method has ref parameters; remove them before creating the job.\");","typeGuard":"public static bool HasNoRefParameters(MethodInfo m)\n    => m != null && m.GetParameters().All(p => !p.ParameterType.IsByRef);","tryCatchPattern":"try { BackgroundJob.Enqueue<T>(x => x.Work()); }\ncatch (NotSupportedException ex) when (ex.Message.Contains(\"passed by reference\")) { /* remove the ref param, return the new value instead */ }","preventionTips":["Never declare ref parameters on job methods; return updated values via the return type.","Wrap ref-parameter library calls in a public method with plain parameters.","Persist mutable shared state in storage keyed by job ID rather than relying on ref."],"tags":["not-supported","job-definition","ref-parameter","serialization"],"backgroundTag":null,"analyzedSha":"c236dd0f930f831ec151e436e138ddc429a02a72","analyzedAt":"2026-08-13T20:27:11.027Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}