dotnet/yarp · error · ArgumentNullException

Header values must be not be empty.

Error message

Header values must be not be empty.

What it means

Thrown by the HeaderMatcher constructor when the `values` collection is non-null but contains at least one null or empty string element. The check uses `values.Any(string.IsNullOrEmpty)`, so a single blank entry trips it. Note: thrown as ArgumentNullException despite being a content/argument problem, and the message text itself has a typo ('must be not be empty').

Source

Thrown at src/ReverseProxy/Routing/HeaderMatcher.cs:37

    /// </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>
    /// Name of the header to look for.
    /// </summary>
    public string Name { get; }

    /// <summary>
    /// Returns a read-only collection of acceptable header values used during routing.
    /// At least one value is required unless <see cref="Mode"/> is set to <see cref="HeaderMatchMode.Exists"/>
    /// or <see cref="HeaderMatchMode.NotExists"/>.

View on GitHub (pinned to bd11867bee)

Solutions

  1. Filter out null/empty entries before construction: `values = values?.Where(v => !string.IsNullOrEmpty(v)).ToList()`.
  2. Fix the source config to remove blank value tokens.
  3. Add a config validator that rejects header matchers whose values contain empty strings.

Example fix

// before
var values = raw.Split(',') ; // may yield ""
new HeaderMatcher("X-Hdr", values, HeaderMatchMode.ExactHeader, false);
// after
var values = raw.Split(',', StringSplitOptions.RemoveEmptyEntries);
new HeaderMatcher("X-Hdr", values, HeaderMatchMode.ExactHeader, false);
Defensive patterns

Strategy: validation

Validate before calling

values = values?.Where(v => !string.IsNullOrEmpty(v)).ToList();
if (values is not null && values.Any(string.IsNullOrEmpty)) throw new ArgumentException("blank value");

Type guard

static bool HasNoBlankValues(IReadOnlyList<string>? values) =>
    values is null || values.All(v => !string.IsNullOrEmpty(v));

Prevention

When it happens

Trigger: Calling `new HeaderMatcher(name, values, mode, ...)` where `values` includes an element that is `null` or `string.Empty`. Commonly arises when binding config where a value token is omitted or whitespace-trimmed to empty.

Common situations: JSON config like `"values": ["", "v2"]` or `"values": [null]`. Programmatically building values from a split operation that yields empty segments. Config generated from user input that was not sanitized.

Related errors


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