devlooped/moq · error · ArgumentNullException

Value cannot be null. (Parameter 'value')

Error message

Value cannot be null. (Parameter 'value')

What it means

Moq allows replacing the expression compiler it uses via the static ExpressionCompiler.Instance property. The setter guards the library's invariant that a compiler must always be present; assigning null would break every later mock that compiles expressions, so it throws ArgumentNullException for parameter 'value' immediately.

Solutions

  1. Only assign a non-null ExpressionCompiler instance; store the previous value and restore that instead of null.
  2. Null-check the compiler obtained from your factory/DI container before assigning it to Instance.
  3. If you want default behavior, do not assign the property at all — it already defaults to Default; there is no need to reset via null.
  4. Wrap assignment in a guard that throws a descriptive error when the resolved compiler is null so the root cause (factory failure) surfaces.

Example fix

// before
ExpressionCompiler.Instance = _container.Resolve<ExpressionCompiler>(); // may be null
// after
var compiler = _container.Resolve<ExpressionCompiler>();
if (compiler != null) ExpressionCompiler.Instance = compiler;
Defensive patterns

Strategy: validation

Validate before calling

var compiler = ResolveCompiler();
if (compiler == null) throw new InvalidOperationException("Resolved ExpressionCompiler was null");
ExpressionCompiler.Instance = compiler;

Type guard

static bool CanSet(ExpressionCompiler? c) => c is not null;

Try / catch

try
{
    ExpressionCompiler.Instance = resolved;
}
catch (ArgumentNullException)
{
    // keep previous/default instance; log factory failure
}

Prevention

When it happens

Trigger: Assigning null to `ExpressionCompiler.Instance`, e.g. `ExpressionCompiler.Instance = null;` or passing a variable that is null at assignment time (uninitialized factory result, failed resolution, reset code).

Common situations: Custom compiler factories that return null on failure; DI containers resolving the compiler to null; cleanup/reset code that tries to 'clear' the instance by assigning null; test teardown ordering issues.

Related errors


AI-assisted analysis of devlooped/moq@89a5be629c (2026-09-16). Data as JSON: /api/errors/a87638a89807412f. Report an issue: GitHub.

Appendix: source

Thrown at src/Moq/ExpressionCompiler.cs:31

    /// </summary>
    [EditorBrowsable(EditorBrowsableState.Advanced)]
    public abstract class ExpressionCompiler
    {
        static ExpressionCompiler instance = DefaultExpressionCompiler.Instance;

        /// <summary>
        ///   The default <see cref="ExpressionCompiler"/> instance, which simply delegates to the framework's <see cref="LambdaExpression.Compile"/>.
        /// </summary>
        public static ExpressionCompiler Default => DefaultExpressionCompiler.Instance;

        /// <summary>
        ///   Gets or sets the <see cref="ExpressionCompiler"/> instance that Moq uses to compile <see cref="Expression"/> (LINQ expression trees).
        ///   Defaults to <see cref="Default"/>.
        /// </summary>
        public static ExpressionCompiler Instance
        {
            get => instance;
            set => instance = value ?? throw new ArgumentNullException(nameof(value));
        }

        /// <summary>
        ///   Initializes a new instance of the <see cref="ExpressionCompiler"/> class.
        /// </summary>
        protected ExpressionCompiler()
        {
        }

        /// <summary>
        ///   Compiles the specified LINQ expression tree.
        /// </summary>
        /// <param name="expression">The LINQ expression tree that should be compiled.</param>
        public abstract Delegate Compile(LambdaExpression expression);

        /// <summary>
        ///   Compiles the specified LINQ expression tree.
        /// </summary>

View on GitHub (pinned to 89a5be629c)