{"record":{"id":"e519531bc9c8fb8d","repo":"vectordotdev/vector","slug":"api-key-should-be-only-valid-ascii-characters","errorCode":null,"errorMessage":"API key should be only valid ASCII characters","messagePattern":"API key should be only valid ASCII characters","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/sinks/datadog/metrics/service.rs","lineNumber":64,"sourceCode":"    pub content_type: &'static str,\n    pub content_encoding: &'static str,\n    pub finalizers: EventFinalizers,\n    pub metadata: RequestMetadata,\n}\n\nimpl DatadogMetricsRequest {\n    /// Converts this request to a `hyper`-compatible request.\n    ///\n    /// # Errors\n    ///\n    /// If any of the header names or values are invalid, or if the URI is invalid, an error variant\n    /// will be returned.\n    pub fn into_http_request(self, api_key: HeaderValue) -> http::Result<Request<Body>> {\n        // use the API key from the incoming event if it is provided\n        let api_key = self.api_key.map_or_else(\n            || api_key,\n            |key| {\n                HeaderValue::from_str(&key).expect(\"API key should be only valid ASCII characters\")\n            },\n        );\n        let request = Request::post(self.uri)\n            .header(\"DD-API-KEY\", api_key)\n            // TODO: The Datadog Agent sends this header to indicate the version of the Go library\n            // it uses which contains the Protocol Buffers definitions used for the Sketches API.\n            // We've copypasted the proto file for now -- `proto/ddsketch.rs`, a partial chunk of\n            // `DataDog/agent-payload/proto/metrics/agent_payload.proto` -- and are thus hardcoding\n            // the version that we copypasted from.\n            //\n            // In the future, we should likely figure out a way to depend on/submodule-ize the\n            // `agent-payload` repo so we can always have an up-to-date proto definition, and be\n            // able to programmatically set the version of the repo so we don't need to hardcode\n            // this header.\n            .header(\"DD-Agent-Payload\", \"4.87.0\")\n            .header(CONTENT_TYPE, self.content_type)\n            .header(CONTENT_ENCODING, self.content_encoding);\n","sourceCodeStart":46,"sourceCodeEnd":82,"githubUrl":"https://github.com/vectordotdev/vector/blob/3708c39b12a93212ed8b8d7510b4cc7769cb5864/src/sinks/datadog/metrics/service.rs#L46-L82","documentation":"Datadog metrics requests can override the API key per event; the override string is converted with HeaderValue::from_str, which accepts only visible ASCII. This expect fires when an event-supplied API key contains non-ASCII bytes, control characters (including newlines), or other characters the header grammar rejects.","triggerScenarios":"A datadog_metrics sink with per-event API key overrides where the event field supplying the key contains a newline, trailing whitespace, non-ASCII characters, or quote characters.","commonSituations":"Keys templated from event fields polluted with whitespace; upstream systems choosing the key from unvalidated data; smart quotes introduced by copy-paste.","solutions":["Sanitize the event field used for the API key in a remap transform (trim whitespace, assert printable ASCII) before the sink","Guard with VRL: drop events whose key field fails a printable-ASCII regex","Drop the per-event override and rely on the sink-level api_key if overrides are not required","Audit which sources can set the override field and constrain them"],"exampleFix":"# before\n[transforms.pre]\ntype = \"remap\"\nsource = '.dd_api_key = .tenant_key'\n\n# after\n[transforms.pre]\ntype = \"remap\"\nsource = '.dd_api_key = replace(string!(.tenant_key), r\"\\\\s\", \"\")'","handlingStrategy":"validation","validationCode":"# VRL: validate event-supplied API key before the sink\nkey = string(.dd_api_key) ?? \"\"\nif !contains(key, \" \") && key =~ r'^[\\x21-\\x7e]+$' {\n  .dd_api_key = key\n} else {\n  abort\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Constrain which sources can set the per-event API key field","Strip whitespace in a remap transform upstream of datadog_metrics","Treat the key field as untrusted input; validate charset like any header"],"tags":["rust","vector","datadog","http-headers","ascii","panic"],"backgroundTag":"invalid-header-value","analyzedSha":"3708c39b12a93212ed8b8d7510b4cc7769cb5864","analyzedAt":"2026-08-20T07:02:18.786Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T20:17:18.057Z"}