{"record":{"id":"c27e45f1e83eeedb","repo":"dotnet/yarp","slug":"headername-cannot-be-null-or-empty-c27e45","errorCode":null,"errorMessage":"'headerName' cannot be null or empty.","messagePattern":"'headerName' cannot be null or empty\\.","errorType":"validation","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/ReverseProxy/Transforms/RequestHeaderTransform.cs","lineNumber":16,"sourceCode":"// Licensed to the .NET Foundation under one or more agreements.\n// The .NET Foundation licenses this file to you under the MIT license.\n\nusing System;\nusing System.Threading.Tasks;\nusing Microsoft.Extensions.Primitives;\n\nnamespace Yarp.ReverseProxy.Transforms;\n\npublic abstract class RequestHeaderTransform : RequestTransform\n{\n    protected RequestHeaderTransform(string headerName, bool append)\n    {\n        if (string.IsNullOrEmpty(headerName))\n        {\n            throw new ArgumentException($\"'{nameof(headerName)}' cannot be null or empty.\", nameof(headerName));\n        }\n\n        Append = append;\n        HeaderName = headerName;\n    }\n\n    internal bool Append { get; }\n    internal string HeaderName { get; }\n\n    public override ValueTask ApplyAsync(RequestTransformContext context)\n    {\n        ArgumentNullException.ThrowIfNull(context);\n\n        var value = GetValue(context);\n        if (value is null)\n        {\n            return default;\n        }","sourceCodeStart":1,"sourceCodeEnd":34,"githubUrl":"https://github.com/dotnet/yarp/blob/bd11867bee7df522e7fd3effb08a9c85fd616908/src/ReverseProxy/Transforms/RequestHeaderTransform.cs#L1-L34","documentation":"RequestHeaderTransform (the abstract base for header-based request transforms) rejects a null/empty headerName in its protected constructor. All derived header transforms inherit this guard, so any subclass constructed without a concrete header name fails here.","triggerScenarios":"Deriving from RequestHeaderTransform (or using RequestHeaderValueTransform) and passing a null/empty headerName to the base constructor. Reached via config when the header name portion of a RequestHeader transform resolves to empty.","commonSituations":"A custom RequestHeaderTransform subclass whose header-name argument is uninitialised; config with an empty RequestHeader value; a programmatic AddTransform callback with a cleared variable.","solutions":["Pass a concrete header name to the base constructor.","Populate the config 'RequestHeader' value with a real header name.","Add a guard at the construction call site."],"exampleFix":"// before\nbase(headerName: \"\", append: true)\n// after\nbase(headerName: \"X-Custom\", append: true)","handlingStrategy":"validation","validationCode":"if (string.IsNullOrEmpty(headerName))\n    throw new InvalidOperationException(\"A header name is required for RequestHeaderTransform.\");\n// then construct the derived transform","typeGuard":"static bool IsValidHeaderName(string? name)\n    => !string.IsNullOrWhiteSpace(name);","tryCatchPattern":null,"preventionTips":["When subclassing RequestHeaderTransform, validate headerName before calling the base constructor.","Use the built-in extension methods to construct header transforms where possible.","Add a unit test covering empty-header-name rejection."],"tags":["yarp","transforms","argument-validation","headers"],"backgroundTag":null,"analyzedSha":"bd11867bee7df522e7fd3effb08a9c85fd616908","analyzedAt":"2026-08-13T21:29:49.359Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}