dotnet/efcore · error · ArgumentException

Exactly one of '{param1}' or '{param2}' must be set.

Error message

Exactly one of '{param1}' or '{param2}' must be set.

What it means

InExpression models `x IN (...)`. Its private constructor enforces that exactly one of two mutually-exclusive value sources is supplied: an inline list (Values) or a single collection parameter (ValuesParameter). Supplying both or neither throws ArgumentException. This is an internal API contract guard, not normally reachable by end users.

Source

Thrown at src/EFCore.Cosmos/Query/Internal/Expressions/InExpression.cs:54

    /// </summary>
    public InExpression(
        SqlExpression item,
        SqlParameterExpression valuesParameter,
        CoreTypeMapping typeMapping)
        : this(item, values: null, valuesParameter, typeMapping)
    {
    }

    private InExpression(
        SqlExpression item,
        IReadOnlyList<SqlExpression>? values,
        SqlParameterExpression? valuesParameter,
        CoreTypeMapping? typeMapping)
        : base(typeof(bool), typeMapping)
    {
        if ((values is null ? 0 : 1) + (valuesParameter is null ? 0 : 1) != 1)
        {
            throw new ArgumentException(
                CosmosStrings.OneOfTwoValuesMustBeSet(nameof(values), nameof(valuesParameter)));
        }

        Item = item;
        Values = values;
        ValuesParameter = valuesParameter;
    }

    /// <summary>
    ///     This is an internal API that supports the Entity Framework Core infrastructure and not subject to
    ///     the same compatibility standards as public APIs. It may be changed or removed without notice in
    ///     any release. You should only use it directly in your code with extreme caution and knowing that
    ///     doing so can result in application failures when updating to a new Entity Framework Core release.
    /// </summary>
    public virtual SqlExpression Item { get; }

    /// <summary>
    ///     The list of values to search the item in.

View on GitHub (pinned to dbf9771522)

Solutions

  1. Pass exactly one of `values` (IReadOnlyList<SqlExpression>) or `valuesParameter` (SqlParameterExpression) to the InExpression constructor.
  2. Prefer the public Update(...) overloads and the SqlExpressionFactory.In(...) helpers, which preserve the invariant.
  3. If you maintain a fork/extension, add a unit test asserting the exactly-one invariant.

Example fix

// before (internal translator bug)
new InExpression(item, values, valuesParameter, typeMapping);

// after: choose one source
new InExpression(item, values, typeMapping);
// or
new InExpression(item, valuesParameter, typeMapping);
Defensive patterns

Strategy: validation

Validate before calling

// Internal-only API: assert the exactly-one invariant in tests.
static bool ExactlyOneOf<T>(T? a, T? b) where T : class
    => (a is null ? 0 : 1) + (b is null ? 0 : 1) == 1;
Debug.Assert(ExactlyOneOf(values, valuesParameter));

Try / catch

try { var inExpr = new InExpression(item, values, typeMapping); }
catch (ArgumentException ex) when (ex.Message.Contains("must be set"))
{ /* fix the translator to supply exactly one source */ }

Prevention

When it happens

Trigger: Directly constructing InExpression with both values and valuesParameter set, or both null. Reachable only by custom query translators/extensions that build IN expressions, since the public constructors funnel into the private one with exactly one source.

Common situations: Writing a custom Cosmos query translator or extending the pipeline with hand-built InExpression nodes; rarely seen by application developers.

Related errors


AI-assisted analysis of dotnet/efcore@dbf9771522 (2026-08-06). Data as JSON: /api/errors/85656e07212fa68d. Report an issue: GitHub.