HangfireIO/Hangfire · error · NotSupportedException

Parameters, passed by reference, are not supported: there is

Error message

Parameters, passed by reference, are not supported: there is no guarantee that specified method will be invoked inside the same process.

What it means

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.

Source

Thrown at src/Hangfire.Core/Common/Job.cs:526

                    "Argument count must be equal to method parameter count.",
                    argumentParameterName);
            }

            foreach (var parameter in parameters)
            {
                // There is no guarantee that specified method will be invoked
                // in the same process. Therefore, output parameters and parameters
                // passed by reference are not supported.

                if (parameter.IsOut)
                {
                    throw new NotSupportedException(
                        "Output parameters are not supported: there is no guarantee that specified method will be invoked inside the same process.");
                }

                if (parameter.ParameterType.IsByRef)
                {
                    throw new NotSupportedException(
                        "Parameters, passed by reference, are not supported: there is no guarantee that specified method will be invoked inside the same process.");
                }

                var parameterTypeInfo = parameter.ParameterType.GetTypeInfo();
                
                if (parameterTypeInfo.IsSubclassOf(typeof(Delegate)) || parameterTypeInfo.IsSubclassOf(typeof(Expression)))
                {
                    throw new NotSupportedException(
                        "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.");
                }
            }
        }

        private static object[] GetExpressionValues(ReadOnlyCollection<Expression> expressions)
        {
            var result = expressions.Count > 0 ? new object[expressions.Count] : [];
            var index = 0;

View on GitHub (pinned to c236dd0f93)

Solutions

  1. Remove the ref modifier; pass the value by value and return the updated value via the method's return type.
  2. Wrap the ref-based method in a public method with plain parameters and enqueue the wrapper.
  3. If mutation semantics are required, persist the value in storage keyed by job ID and read/write it inside the job body.

Example fix

// before — ref parameter, unsupported
public class Worker {
    public void Run(ref int counter) { counter++; }
}

// after — return the new value
public class Worker {
    public int Run(int counter) { return counter + 1; }
}
BackgroundJob.Enqueue<Worker>(x => x.Run(0));
Defensive patterns

Strategy: validation

Validate before calling

if (method.GetParameters().Any(p => p.ParameterType.IsByRef))
    throw new NotSupportedException("Job method has ref parameters; remove them before creating the job.");

Type guard

public static bool HasNoRefParameters(MethodInfo m)
    => m != null && m.GetParameters().All(p => !p.ParameterType.IsByRef);

Try / catch

try { BackgroundJob.Enqueue<T>(x => x.Work()); }
catch (NotSupportedException ex) when (ex.Message.Contains("passed by reference")) { /* remove the ref param, return the new value instead */ }

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of HangfireIO/Hangfire@c236dd0f93 (2026-08-13). Data as JSON: /api/errors/5d0ad44f1f221965. Report an issue: GitHub.