{"record":{"id":"9869af1b9b202258","repo":"TechnitiumSoftware/DnsServer","slug":"failed-to-add-header-pair-key","errorCode":null,"errorMessage":"Failed to add header '{pair.Key}'.","messagePattern":"Failed to add header '(.+?)'\\.","errorType":"exception","errorClass":"FormatException","httpStatus":null,"severity":"error","filePath":"Apps/LogExporterApp/Strategy/HttpExportStrategy.cs","lineNumber":100,"sourceCode":"        }\n\n        #endregion\n\n        public class CustomHttpClient : IHttpClient\n        {\n            readonly HttpClient _httpClient;\n\n            public CustomHttpClient()\n            {\n                _httpClient = new HttpClient();\n            }\n\n            public void Configure(IConfiguration configuration)\n            {\n                foreach (IConfigurationSection pair in configuration.GetChildren())\n                {\n                    if (!_httpClient.DefaultRequestHeaders.TryAddWithoutValidation(pair.Key, pair.Value))\n                        throw new FormatException($\"Failed to add header '{pair.Key}'.\");\n                }\n            }\n\n            public void Dispose()\n            {\n                _httpClient?.Dispose();\n                GC.SuppressFinalize(this);\n            }\n\n            public async Task<HttpResponseMessage> PostAsync(string requestUri, Stream contentStream, CancellationToken cancellationToken)\n            {\n                StreamContent content = new StreamContent(contentStream);\n                content.Headers.Add(\"Content-Type\", \"application/json\");\n\n                return await _httpClient\n                    .PostAsync(requestUri, content, cancellationToken)\n                    .ConfigureAwait(false);\n            }","sourceCodeStart":82,"sourceCodeEnd":118,"githubUrl":"https://github.com/TechnitiumSoftware/DnsServer/blob/d0484b6c1e7439cdc53d67d81e9c876cda2ad756/Apps/LogExporterApp/Strategy/HttpExportStrategy.cs#L82-L118","documentation":"Thrown by CustomHttpClient.Configure when HttpClient.DefaultRequestHeaders.TryAddWithoutValidation returns false for a header read from the LogExporter HTTP target configuration. .NET rejects headers with invalid names or values, and the app surfaces that as FormatException with the offending key. It stops the export strategy from silently dropping headers.","triggerScenarios":"The LogExporter HTTP target config contains a 'headers' section where a key or value fails .NET header validation — e.g. a header name with spaces or control characters, or a value containing CR/LF. Each child section becomes one header via TryAddWithoutValidation.","commonSituations":"Typo in a header name, copy-pasting a header with a colon in the key, a value containing a newline, or a misconfigured templated header.","solutions":["Inspect the LogExporter HTTP target 'headers' section and find the key named in the message.","Correct the header name to a valid RFC 7230 token (no spaces, control chars, or delimiters).","Strip any CR/LF or stray quotes from the header value.","Reload the LogExporterApp config."],"exampleFix":"// before\n\"headers\": { \"Content Type\": \"application/json\" }\n// after\n\"headers\": { \"Content-Type\": \"application/json\" }","handlingStrategy":"validation","validationCode":"foreach (IConfigurationSection pair in configuration.GetChildren())\n{\n    if (string.IsNullOrWhiteSpace(pair.Key) || pair.Key.Any(c => c <= 32 || c == ':' || c > 126))\n        throw new ConfigValidationException($\"Invalid HTTP header name '{pair.Key}'.\");\n    if (pair.Value != null && (pair.Value.IndexOfAny(new[] {'\\r','\\n'}) >= 0))\n        throw new ConfigValidationException($\"HTTP header '{pair.Key}' value contains CR/LF.\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Validate header names against RFC 7230 token rules before adding.","Reject header values containing CR/LF.","Lint the LogExporter headers block on deploy."],"tags":["config","log-exporter","http","headers","format-exception"],"backgroundTag":null,"analyzedSha":"d0484b6c1e7439cdc53d67d81e9c876cda2ad756","analyzedAt":"2026-08-13T22:57:35.508Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}