{"record":{"id":"3bd6f9793a18ea29","repo":"dotnet/yarp","slug":"header-values-must-be-not-be-empty","errorCode":null,"errorMessage":"Header values must be not be empty.","messagePattern":"Header values must be not be empty\\.","errorType":"validation","errorClass":"ArgumentNullException","httpStatus":null,"severity":"error","filePath":"src/ReverseProxy/Routing/HeaderMatcher.cs","lineNumber":37,"sourceCode":"    /// </summary>\n    public HeaderMatcher(string name, IReadOnlyList<string>? values, HeaderMatchMode mode, bool isCaseSensitive)\n    {\n        if (string.IsNullOrEmpty(name))\n        {\n            throw new ArgumentException(\"A header name is required.\", nameof(name));\n        }\n        if ((mode != HeaderMatchMode.Exists && mode != HeaderMatchMode.NotExists)\n            && (values is null || values.Count == 0))\n        {\n            throw new ArgumentException(\"Header values must have at least one value.\", nameof(values));\n        }\n        if ((mode == HeaderMatchMode.Exists || mode == HeaderMatchMode.NotExists) && values?.Count > 0)\n        {\n            throw new ArgumentException($\"Header values must not be specified when using '{mode}'.\", nameof(values));\n        }\n        if (values is not null && values.Any(string.IsNullOrEmpty))\n        {\n            throw new ArgumentNullException(nameof(values), \"Header values must be not be empty.\");\n        }\n\n        Name = name;\n        Values = values?.ToArray() ?? Array.Empty<string>();\n        Mode = mode;\n        Comparison = isCaseSensitive ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase;\n        Separator = name.Equals(HeaderNames.Cookie, StringComparison.OrdinalIgnoreCase) ? ';' : ',';\n    }\n\n    /// <summary>\n    /// Name of the header to look for.\n    /// </summary>\n    public string Name { get; }\n\n    /// <summary>\n    /// Returns a read-only collection of acceptable header values used during routing.\n    /// At least one value is required unless <see cref=\"Mode\"/> is set to <see cref=\"HeaderMatchMode.Exists\"/>\n    /// or <see cref=\"HeaderMatchMode.NotExists\"/>.","sourceCodeStart":19,"sourceCodeEnd":55,"githubUrl":"https://github.com/dotnet/yarp/blob/bd11867bee7df522e7fd3effb08a9c85fd616908/src/ReverseProxy/Routing/HeaderMatcher.cs#L19-L55","documentation":"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').","triggerScenarios":"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.","commonSituations":"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.","solutions":["Filter out null/empty entries before construction: `values = values?.Where(v => !string.IsNullOrEmpty(v)).ToList()`.","Fix the source config to remove blank value tokens.","Add a config validator that rejects header matchers whose values contain empty strings."],"exampleFix":"// before\nvar values = raw.Split(',') ; // may yield \"\"\nnew HeaderMatcher(\"X-Hdr\", values, HeaderMatchMode.ExactHeader, false);\n// after\nvar values = raw.Split(',', StringSplitOptions.RemoveEmptyEntries);\nnew HeaderMatcher(\"X-Hdr\", values, HeaderMatchMode.ExactHeader, false);","handlingStrategy":"validation","validationCode":"values = values?.Where(v => !string.IsNullOrEmpty(v)).ToList();\nif (values is not null && values.Any(string.IsNullOrEmpty)) throw new ArgumentException(\"blank value\");","typeGuard":"static bool HasNoBlankValues(IReadOnlyList<string>? values) =>\n    values is null || values.All(v => !string.IsNullOrEmpty(v));","tryCatchPattern":null,"preventionTips":["Sanitize split results with StringSplitOptions.RemoveEmptyEntries.","Reject empty header-value tokens in config validation.","Add a unit test that feeds [\"\", \"x\"] to confirm your guard fires."],"tags":["routing","header-match","argument-validation","yarp"],"backgroundTag":null,"analyzedSha":"bd11867bee7df522e7fd3effb08a9c85fd616908","analyzedAt":"2026-08-13T21:29:49.359Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}