dotnet/yarp · error · ArgumentException
Header values must have at least one value.
Error message
Header values must have at least one value.
What it means
The `HeaderMatcher` constructor requires at least one value for matching modes that compare values (`ExactHeader`, `HeaderPrefix`, `Contains`, `NotContains`). Only `Exists` and `NotExists` modes are exempt because they don't need values. This validation ensures the matcher has the data it needs to perform the comparison.
Source
Thrown at src/ReverseProxy/Routing/HeaderMatcher.cs:29
/// <summary>
/// A request header matcher used during routing.
/// </summary>
internal sealed class HeaderMatcher
{
/// <summary>
/// Creates a new instance.
/// </summary>
public HeaderMatcher(string name, IReadOnlyList<string>? values, HeaderMatchMode mode, bool isCaseSensitive)
{
if (string.IsNullOrEmpty(name))
{
throw new ArgumentException("A header name is required.", nameof(name));
}
if ((mode != HeaderMatchMode.Exists && mode != HeaderMatchMode.NotExists)
&& (values is null || values.Count == 0))
{
throw new ArgumentException("Header values must have at least one value.", nameof(values));
}
if ((mode == HeaderMatchMode.Exists || mode == HeaderMatchMode.NotExists) && values?.Count > 0)
{
throw new ArgumentException($"Header values must not be specified when using '{mode}'.", nameof(values));
}
if (values is not null && values.Any(string.IsNullOrEmpty))
{
throw new ArgumentNullException(nameof(values), "Header values must be not be empty.");
}
Name = name;
Values = values?.ToArray() ?? Array.Empty<string>();
Mode = mode;
Comparison = isCaseSensitive ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase;
Separator = name.Equals(HeaderNames.Cookie, StringComparison.OrdinalIgnoreCase) ? ';' : ',';
}
/// <summary>View on GitHub (pinned to bd11867bee)
Solutions
- If you want to match on header existence, set `Mode` to `"Exists"` (or `"NotExists"`) and omit values — this is the most common fix.
- If matching on specific values, populate the `Values` array with at least one value: `{ "Header": "X-Key", "Values": ["expected-value"] }`.
- Verify the JSON structure — `Values` must be an array of strings, not a single string value.
- Check for trailing commas or missing entries in the values array that could produce an empty collection.
Example fix
// before — values missing with default ExactHeader mode
"Headers": [
{ "Header": "X-Trace-Id" } // throws — no values, default mode is ExactHeader
]
// after — use Exists mode if you only need header presence
"Headers": [
{ "Header": "X-Trace-Id", "Mode": "Exists" }
]
// or provide values if you need value matching
"Headers": [
{ "Header": "X-Env", "Values": ["prod", "staging"] }
] Defensive patterns
Strategy: validation
Validate before calling
// Validate header match values/mode before adding to route
static bool IsValidHeaderMatchValues(HeaderMatchConfig match)
{
var needsValues = match.Mode is not ("Exists" or "NotExists");
return !needsValues || (match.Values is { Count: > 0 });
} Type guard
static bool IsValidHeaderMatcherConfig(string name, IReadOnlyList<string>? values, HeaderMatchMode mode)
=> !string.IsNullOrEmpty(name)
&& ((mode is HeaderMatchMode.Exists or HeaderMatchMode.NotExists) || (values is { Count: > 0 })); Try / catch
// Not applicable — fix the configuration to provide values or use Exists mode.
Prevention
- If checking header existence, explicitly set Mode to Exists.
- Always provide at least one value for ExactHeader, HeaderPrefix, Contains, and NotContains modes.
- Validate dynamic config generation to ensure header match values are populated.
When it happens
Trigger: A route header match is configured with a mode like `ExactHeader` (the default) but with an empty or null `Values` array (e.g., `{ "Header": "X-Key", "Values": [] }` or `{ "Header": "X-Key" }` without specifying values and without setting `Mode` to `Exists`). The constructor check at line 26-30 detects `values is null || values.Count == 0` and throws.
Common situations: A developer wants to check header *existence* but doesn't set `Mode: "Exists"` — the default mode is `ExactHeader`, which requires values. A config template has a placeholder values array that was never populated. A dynamic config provider omits values when they should have been populated.
Related errors
- A header name is required.
- A non-empty CustomTransform value is required
- A non-empty CustomMetadata value is required
- Unable to load or apply the proxy configuration.
- The proxy config is invalid.
AI-assisted analysis of dotnet/yarp@bd11867bee (2026-08-13).
Data as JSON: /api/errors/2ed2be8b6aa0136f.
Report an issue: GitHub.