FlowiseAI/Flowise · error · Error
Invalid header "${key}": value must be a string
Error message
Invalid header "${key}": value must be a string What it means
Thrown by validateCustomHeaders() when a header value is not a JavaScript string. The validator enforces that every value in the headers bag is a string before it is forwarded to an outbound HTTP request, preventing accidental serialization of numbers, booleans, objects, or arrays into header lines. This is a type-enforcement guard, not a network-level check.
Source
Thrown at packages/components/src/headerValidation.ts:66
for (const [key, value] of entries) {
if (typeof key !== 'string' || key.length === 0) {
throw new Error('Invalid header: key must be a non-empty string')
}
if (key.length > MAX_KEY_LENGTH) {
throw new Error(`Invalid header "${key}": key exceeds ${MAX_KEY_LENGTH} chars`)
}
if (!RFC7230_TOKEN.test(key)) {
throw new Error(`Invalid header "${key}": key contains illegal characters`)
}
const lower = key.toLowerCase()
if (DENIED_HEADER_NAMES.has(lower) || DENIED_HEADER_PREFIXES.some((p) => lower.startsWith(p))) {
throw new Error(`Invalid header "${key}": this header name is not allowed`)
}
if (typeof value !== 'string') {
throw new Error(`Invalid header "${key}": value must be a string`)
}
if (value.length > MAX_VALUE_LENGTH) {
throw new Error(`Invalid header "${key}": value exceeds ${MAX_VALUE_LENGTH} chars`)
}
for (let i = 0; i < value.length; i++) {
const code = value.charCodeAt(i)
if (code === 0x0d || code === 0x0a || (code < 0x20 && code !== 0x09)) {
throw new Error(`Invalid header "${key}": value contains illegal control characters`)
}
}
}
}
/**
* Returns a copy of `headers` with credential-bearing entries (Authorization, Cookie, X-Api-Key, …)
* replaced by a placeholder string. Used at trust boundaries before a header bag is exposed to flow
* templates, observers, or logs. Comparison is case-insensitive; non-sensitive headers pass through.
*/View on GitHub (pinned to abe4a8601a)
Solutions
- Coerce every header value to a string before calling validateCustomHeaders: build the headers object with template literals or String().
- Audit the headers object at the call site and convert numeric/boolean values explicitly.
- If the value can legitimately be non-string, drop the header or stringify it intentionally rather than letting it through raw.
Example fix
// before
validateCustomHeaders({ 'X-Retry-Count': retries, 'X-Verbose': true })
// after
validateCustomHeaders({ 'X-Retry-Count': String(retries), 'X-Verbose': String(true) }) Defensive patterns
Strategy: validation
Validate before calling
// Pre-validate that every header value is a string before calling validateCustomHeaders
function safeHeaders(input: Record<string, unknown>): Record<string, string> {
const out: Record<string, string> = {}
for (const [k, v] of Object.entries(input)) {
if (typeof v !== 'string') {
throw new Error(`Header '${k}' must be a string, got ${typeof v}`)
}
out[k] = v
}
return out
}
const safe = safeHeaders(rawHeaders)
validateCustomHeaders(safe) Type guard
function isStringHeaders(h: Record<string, unknown>): h is Record<string, string> {
return Object.values(h).every((v) => typeof v === 'string')
} Try / catch
try {
validateCustomHeaders(headers)
} catch (e) {
// surface a user-facing validation error, do not retry
throw new BadRequestError(String(e))
} Prevention
- Always type header bags as Record<string, string> at API boundaries so non-string values fail to compile.
- Coerce known-numeric fields with String() at the point of assignment.
- Run validateCustomHeaders early in request building, before any network call.
When it happens
Trigger: Calling validateCustomHeaders() with a record where any value is a number (e.g. { 'X-Retry-Count': 3 }), a boolean, null, undefined, an array, or an object. The check at line 65 (typeof value !== 'string') fires before any length or character validation.
Common situations: Config objects built from typed application state where numeric fields leak into headers without String(). JSON parsed from external config that contains numeric values. Passing request options straight from a form or API response where numbers are common (retry counts, timeouts, content lengths).
Related errors
- Invalid headers: expected an object
- Invalid headers: too many entries (max ${MAX_HEADERS})
- Invalid header: key must be a non-empty string
- Invalid header "${key}": key exceeds ${MAX_KEY_LENGTH} chars
- Invalid header "${key}": key contains illegal characters
AI-assisted analysis of FlowiseAI/Flowise@abe4a8601a (2026-08-12).
Data as JSON: /api/errors/515519dceae1e0f7.
Report an issue: GitHub.