devlooped/moq · error · ArgumentNullException

Value cannot be null. (Parameter 'newExpression')

Error message

Value cannot be null. (Parameter 'newExpression')

What it means

ConstructorCallVisitor.ExtractArgumentValues extracts constructor arguments from a NewExpression-based lambda. It requires a lambda; passing null throws ArgumentNullException for 'newExpression'. This is an explicit API-contract guard so callers fail fast rather than getting a NullReferenceException inside the visitor.

Solutions

  1. Ensure the lambda expression is constructed before the call, e.g. pass a real `Expression.Lambda(...)` or a typed lambda argument.
  2. Null-check the expression at the call site and fail with a descriptive error identifying the source.
  3. Fix the upstream producer (fixture/factory) that returns null instead of a LambdaExpression.
  4. If the value is optional, branch before calling ExtractArgumentValues rather than relying on it to tolerate null.

Example fix

// before
var args = ConstructorCallVisitor.ExtractArgumentValues(_cachedExpression); // null
// after
if (_cachedExpression != null)
    var args = ConstructorCallVisitor.ExtractArgumentValues(_cachedExpression);
Defensive patterns

Strategy: validation

Validate before calling

if (newExpression == null)
    throw new InvalidOperationException("Lambda for constructor extraction was not built");
var args = ConstructorCallVisitor.ExtractArgumentValues(newExpression);

Type guard

static bool IsUsableLambda(LambdaExpression? e) => e is not null && e.Body is not null;

Try / catch

try
{
    var values = ConstructorCallVisitor.ExtractArgumentValues(lambda);
}
catch (ArgumentNullException ex) when (ex.ParamName == "newExpression")
{
    // rebuild or source the lambda from the caller
}

Prevention

When it happens

Trigger: Calling ExtractArgumentValues(null) directly, or passing the result of an expression-producing helper that returned null (failed resolution, default(T) of a LambdaExpression variable, unassigned field).

Common situations: Custom value providers/fixture integrations that build lambda expressions and can return null; reflection-driven test frameworks passing through unbound values; refactors where an expression variable lost its initializer.

Related errors


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

Appendix: source

Thrown at src/Moq/Expressions/Visitors/ConstructorCallVisitor.cs:26

using System.Linq.Expressions;
using System.Reflection;

using Moq.Properties;

namespace Moq.Expressions.Visitors
{
    class ConstructorCallVisitor : ExpressionVisitor
    {
        /// <summary>
        /// Extracts the arguments from a lambda expression that calls a constructor.
        /// </summary>
        /// <param name="newExpression">The constructor expression.</param>
        /// <returns>Extracted argument values.</returns>
        public static object[] ExtractArgumentValues(LambdaExpression newExpression)
        {
            if (newExpression is null)
            {
                throw new ArgumentNullException(nameof(newExpression));
            }

            var visitor = new ConstructorCallVisitor();
            visitor.Visit(newExpression);

            if (visitor.constructor == null)
            {
                throw new NotSupportedException(Resources.NoConstructorCallFound);
            }

            return visitor.arguments;
        }

        ConstructorInfo? constructor;
        object[] arguments;

#if NULLABLE_REFERENCE_TYPES
        [return: NotNullIfNotNull("node")]

View on GitHub (pinned to 89a5be629c)