dotnet/yarp · error · ArgumentException

Query parameter values must not be specified when using '{na

Error message

Query parameter values must not be specified when using '{nameof(QueryParameterMatchMode.Exists)}'.

What it means

Thrown by the QueryParameterMatcher constructor when Mode is `Exists` but `values` has more than zero entries. Exists mode only checks whether the query parameter is present, so supplying values is contradictory and almost always a config mistake.

Source

Thrown at src/ReverseProxy/Routing/QueryParameterMatcher.cs:29

/// <summary>
/// A request query parameter matcher used during routing.
/// </summary>
internal sealed class QueryParameterMatcher
{
    /// <summary>
    /// Creates a new instance.
    /// </summary>
    public QueryParameterMatcher(string name, IReadOnlyList<string>? values, QueryParameterMatchMode mode, bool isCaseSensitive)
    {
        ArgumentException.ThrowIfNullOrEmpty(name);
        if (mode != QueryParameterMatchMode.Exists
            && (values is null || values.Count == 0))
        {
            throw new ArgumentException("Query parameter values must have at least one value.", nameof(values));
        }
        if (mode == QueryParameterMatchMode.Exists && values?.Count > 0)
        {
            throw new ArgumentException($"Query parameter values must not be specified when using '{nameof(QueryParameterMatchMode.Exists)}'.", nameof(values));
        }
        if (values is not null && values.Any(string.IsNullOrEmpty))
        {
            throw new ArgumentNullException(nameof(values), "Query parameter values must not be empty.");
        }

        Name = name;
        Values = values?.ToArray() ?? Array.Empty<string>();
        Mode = mode;
        Comparison = isCaseSensitive ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase;
    }

    /// <summary>
    /// Name of the query parameter to look for.
    /// </summary>
    public string Name { get; }

    /// <summary>

View on GitHub (pinned to bd11867bee)

Solutions

  1. Remove the values entries for Exists-mode matchers.
  2. If value matching is intended, change Mode to Exact/Prefix/Contains and keep the values.
  3. Add a pre-construction assertion that Exists implies empty values.

Example fix

// before
new QueryParameterMatcher("flag", new[] { "1" }, QueryParameterMatchMode.Exists, false);
// after
new QueryParameterMatcher("flag", values: null, QueryParameterMatchMode.Exists, false);
Defensive patterns

Strategy: validation

Validate before calling

if (mode == QueryParameterMatchMode.Exists && values?.Count > 0)
    throw new InvalidOperationException("Exists mode cannot take values.");

Type guard

static bool IsValidExistsMode(QueryParameterMatchMode mode, IReadOnlyList<string>? values) =>
    mode != QueryParameterMatchMode.Exists || values is null || values.Count == 0;

Prevention

When it happens

Trigger: Constructing `new QueryParameterMatcher(name, values, QueryParameterMatchMode.Exists, ...)` with a non-empty `values` collection, or binding route config that sets both `mode: Exists` and a values list.

Common situations: Switched mode to Exists but left the values array populated. Config template that always emits a default values list.

Related errors


AI-assisted analysis of dotnet/yarp@bd11867bee (2026-08-13). Data as JSON: /api/errors/159e5c867b3f6b5d. Report an issue: GitHub.