dotnet/yarp · error · ArgumentException

Query parameter values must have at least one value.

Error message

Query parameter values must have at least one value.

What it means

Thrown by the QueryParameterMatcher constructor when the match Mode is anything other than `Exists` (e.g. Exact, Prefix, Contains) and the `values` list is null or empty. Non-existence modes require at least one value to compare the query parameter against.

Source

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

using Yarp.ReverseProxy.Configuration;

namespace Yarp.ReverseProxy.Routing;

/// <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.

View on GitHub (pinned to bd11867bee)

Solutions

  1. Supply at least one value string for non-Exists modes.
  2. If presence-only semantics are intended, switch Mode to `Exists` and omit values.
  3. Validate config: assert `(mode == Exists) || (values?.Count > 0)` before construction.

Example fix

// before
new QueryParameterMatcher("t", null, QueryParameterMatchMode.Exact, false);
// after
new QueryParameterMatcher("t", new[] { "json" }, QueryParameterMatchMode.Exact, false);
Defensive patterns

Strategy: validation

Validate before calling

if (mode != QueryParameterMatchMode.Exists && (values is null || values.Count == 0))
    throw new InvalidOperationException("Non-Exists query match requires values.");

Type guard

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

Prevention

When it happens

Trigger: Constructing `new QueryParameterMatcher(name, values, mode, isCaseSensitive)` with `mode != QueryParameterMatchMode.Exists` and `values` null or zero-length. Reached via YARP route config binding a query-parameter match without values.

Common situations: Config sets `mode: Exact` but omits `values`. Copy-paste from an Exists rule without adding values. Generated config that drops the values array when it's a single empty default.

Related errors


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