vectordotdev/vector · error

error creating request

Error message

error creating request

What it means

In the shared HTTP client used by HTTP-based sources, `builder.body(body).expect("error creating request")` fires when the http crate rejects the request parts before sending. The most common cause is a header value that is not a legal HeaderValue (control characters, newline, non-visible-ASCII bytes) coming from `inputs.headers` or auth configuration; a malformed request target built from the configured endpoint also triggers it. The comment says building should be infallible — it is only infallible if all inputs are valid HTTP.

Source

Thrown at src/sources/util/http_client.rs:215

            }

            // Get the request body from the context (if any)
            let body = match context.get_request_body() {
                Some(body_str) => {
                    // Set Content-Type header if not already set
                    if !inputs
                        .headers
                        .contains_key(http::header::CONTENT_TYPE.as_str())
                    {
                        builder = builder.header(http::header::CONTENT_TYPE, "application/json");
                    }
                    Body::from(body_str)
                }
                None => Body::empty(),
            };

            // building the request should be infallible
            let mut request = builder.body(body).expect("error creating request");

            if let Some(auth) = &inputs.auth {
                auth.apply(&mut request);
            }

            tokio::time::timeout(inputs.timeout, client.send(request))
                .then(move |result| async move {
                    match result {
                        Ok(Ok(response)) => Ok(response),
                        Ok(Err(error)) => Err(error.into()),
                        Err(_) => Err(format!(
                            "Timeout error: request exceeded {}s",
                            inputs.timeout.as_secs_f64()
                        )
                        .into()),
                    }
                })
                .and_then(|response| async move {

View on GitHub (pinned to 3708c39b12)

Solutions

  1. Sanitize configured header values: trim whitespace and strip newlines; base64-encode binary tokens
  2. Ensure the endpoint is an absolute, properly percent-encoded URL
  3. If embedding: pre-validate every header with `http::HeaderValue::from_str(...)` and surface a config error instead of panicking

Example fix

// before
let mut request = builder.body(body).expect("error creating request");
// after
for (name, value) in &inputs.headers {
    http::HeaderValue::from_str(value)
        .map_err(|e| format!("invalid value for header {name}: {e}"))?;
}
let mut request = builder.body(body).expect("error creating request");
Defensive patterns

Strategy: validation

Validate before calling

// Rust: validate all configured headers and endpoint before the poller starts
for (name, value) in &config.headers {
    http::HeaderValue::from_str(value)
        .with_context(|| format!("invalid value for header {name}"))?;
}
http::Uri::try_from(&config.endpoint)?;

Type guard

fn valid_header_value(value: &str) -> bool {
    http::HeaderValue::from_str(value).is_ok()
}

Prevention

When it happens

Trigger: An `inputs.headers` entry (or auth token) containing raw newline/tab or non-ASCII bytes; an endpoint URL with spaces or unencoded characters that yields an invalid request URI when `builder.body()` validates the parts.

Common situations: API keys or bearer tokens pasted into config with trailing newlines or unicode quotes; endpoints copied from browsers containing spaces/unencoded characters; header values generated by templating scripts that inject bad bytes.

Related errors


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