vectordotdev/vector · error

API key should be only valid ASCII characters

Error message

API key should be only valid ASCII characters

What it means

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.

Source

Thrown at src/sinks/datadog/metrics/service.rs:64

    pub content_type: &'static str,
    pub content_encoding: &'static str,
    pub finalizers: EventFinalizers,
    pub metadata: RequestMetadata,
}

impl DatadogMetricsRequest {
    /// Converts this request to a `hyper`-compatible request.
    ///
    /// # Errors
    ///
    /// If any of the header names or values are invalid, or if the URI is invalid, an error variant
    /// will be returned.
    pub fn into_http_request(self, api_key: HeaderValue) -> http::Result<Request<Body>> {
        // use the API key from the incoming event if it is provided
        let api_key = self.api_key.map_or_else(
            || api_key,
            |key| {
                HeaderValue::from_str(&key).expect("API key should be only valid ASCII characters")
            },
        );
        let request = Request::post(self.uri)
            .header("DD-API-KEY", api_key)
            // TODO: The Datadog Agent sends this header to indicate the version of the Go library
            // it uses which contains the Protocol Buffers definitions used for the Sketches API.
            // We've copypasted the proto file for now -- `proto/ddsketch.rs`, a partial chunk of
            // `DataDog/agent-payload/proto/metrics/agent_payload.proto` -- and are thus hardcoding
            // the version that we copypasted from.
            //
            // In the future, we should likely figure out a way to depend on/submodule-ize the
            // `agent-payload` repo so we can always have an up-to-date proto definition, and be
            // able to programmatically set the version of the repo so we don't need to hardcode
            // this header.
            .header("DD-Agent-Payload", "4.87.0")
            .header(CONTENT_TYPE, self.content_type)
            .header(CONTENT_ENCODING, self.content_encoding);

View on GitHub (pinned to 3708c39b12)

Solutions

  1. Sanitize the event field used for the API key in a remap transform (trim whitespace, assert printable ASCII) before the sink
  2. Guard with VRL: drop events whose key field fails a printable-ASCII regex
  3. Drop the per-event override and rely on the sink-level api_key if overrides are not required
  4. Audit which sources can set the override field and constrain them

Example fix

# before
[transforms.pre]
type = "remap"
source = '.dd_api_key = .tenant_key'

# after
[transforms.pre]
type = "remap"
source = '.dd_api_key = replace(string!(.tenant_key), r"\\s", "")'
Defensive patterns

Strategy: validation

Validate before calling

# VRL: validate event-supplied API key before the sink
key = string(.dd_api_key) ?? ""
if !contains(key, " ") && key =~ r'^[\x21-\x7e]+$' {
  .dd_api_key = key
} else {
  abort
}

Prevention

When it happens

Trigger: 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.

Common situations: Keys templated from event fields polluted with whitespace; upstream systems choosing the key from unvalidated data; smart quotes introduced by copy-paste.

Related errors


AI-assisted analysis of vectordotdev/vector@3708c39b12 (2026-08-20). Data as JSON: /api/errors/e519531bc9c8fb8d. Report an issue: GitHub.