BoundaryML/baml · error

baml.fetch_as: expected header value to be a string, got {}

Error message

baml.fetch_as: expected header value to be a string, got {}

What it means

Runtime type-validation error inside the baml.fetch_as host function: the `headers` field of the request argument carried a value that is not a string (e.g. an int or nested map) when building the HTTP HeaderMap. The per-header type check fires during request construction, before any network I/O.

Source

Thrown at engine/baml-runtime/src/async_vm_runtime.rs:643

                                                    _ => break 'res Err(anyhow!(
                                                        "baml.fetch_as: expected method to be a valid HTTP method, got {}",
                                                        method
                                                    ))
                                                };

                                                if let Some(BamlValue::Map(headers)) = fields.get("headers") {
                                                    let mut header_map = reqwest::header::HeaderMap::new();

                                                    for (k, v) in headers {
                                                        let Ok(key) = reqwest::header::HeaderName::from_str(k) else {
                                                            break 'res Err(anyhow!(
                                                                "baml.fetch_as: expected header key to be a valid HTTP header name, got {}",
                                                                k
                                                            ));
                                                        };

                                                        let Some(value_as_string) = v.as_str() else {
                                                            break 'res Err(anyhow!(
                                                                "baml.fetch_as: expected header value to be a string, got {}",
                                                                v
                                                            ));
                                                        };

                                                        let Ok(value) = reqwest::header::HeaderValue::from_str(value_as_string) else {
                                                            break 'res Err(anyhow!(
                                                                "baml.fetch_as: expected header value to be a string, got {}",
                                                                v
                                                            ));
                                                        };

                                                        header_map.insert(key, value);
                                                    }

                                                    req = req.headers(header_map);
                                                }

View on GitHub (pinned to bd85ce9dee)

Solutions

  1. Convert header values to strings before putting them in the headers map (e.g. 42 → "42")
  2. Ensure variables used as header values are non-null strings at runtime
  3. Restructure headers so only string values are included

Example fix

// before (BAML)
let req = baml.HttpRequest{url: "https://api.example.com", method: "Get", headers: {"Content-Length": 42}}
// after
let req = baml.HttpRequest{url: "https://api.example.com", method: "Get", headers: {"Content-Length": "42"}}
Defensive patterns

Strategy: type-guard

Validate before calling

function validateHeaderValues(headers) {
  for (const [k, v] of Object.entries(headers || {})) {
    if (typeof v !== 'string') throw new Error(`Header "${k}" must be a string, got ${typeof v}: ${JSON.stringify(v)}`);
  }
}

Type guard

function isStringHeaderMap(h) {
  return h !== null && typeof h === 'object' && Object.values(h).every(v => typeof v === 'string');
}

Try / catch

try {
  const data = await runtime.callFunction(fnName, args);
} catch (e) {
  if (String(e).includes('expected header value to be a string')) {
    // coerce numeric/boolean header values with String(v) and retry
  } else throw e;
}

Prevention

When it happens

Trigger: Passing a header value that is not a string, e.g. headers{"Content-Length": 42} or a null value from an unresolved variable.

Common situations: Numeric or boolean header values (content-length, retries), headers built from JSON where numbers stay numbers, or template variables that resolve to null.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


AI-assisted analysis of BoundaryML/baml@bd85ce9dee (2026-09-12). Data as JSON: /api/errors/8be287fd4f80040d. Report an issue: GitHub.