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
- Remove the values entries for Exists-mode matchers.
- If value matching is intended, change Mode to Exact/Prefix/Contains and keep the values.
- 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 switching a query match to Exists, clear the values list.
- Add config validation that Exists implies empty values.
- Avoid config templates that always inject a default values array.
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
- Query parameter values must have at least one value.
- Query parameter values must not be empty.
- Header values must not be specified when using '{mode}'.
- Header values must be not be empty.
- '{nameof(routeValueKey)}' cannot be null or empty.
AI-assisted analysis of dotnet/yarp@bd11867bee (2026-08-13).
Data as JSON: /api/errors/159e5c867b3f6b5d.
Report an issue: GitHub.