FlowiseAI/Flowise · error · Error
Invalid header: key must be a non-empty string
Error message
Invalid header: key must be a non-empty string
What it means
Per-entry guard: each key must be a non-empty string. Plain-object keys are always strings, so this primarily catches empty-string keys ({"": "v"}) or numeric/array-like keys that slip through when an array is passed (Object.entries on an array yields ['0', value]).
Source
Thrown at packages/components/src/headerValidation.ts:51
/**
* Validates a set of user-supplied HTTP headers intended for outbound requests.
* Rejects malformed keys, CRLF/control-char injection in values, hop-by-hop and
* sensitive header names, and oversized payloads. Throws a plain Error; callers
* are responsible for mapping to their own error types.
*/
export function validateCustomHeaders(headers: Record<string, string>): void {
if (!headers || typeof headers !== 'object') {
throw new Error('Invalid headers: expected an object')
}
const entries = Object.entries(headers)
if (entries.length > MAX_HEADERS) {
throw new Error(`Invalid headers: too many entries (max ${MAX_HEADERS})`)
}
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`)View on GitHub (pinned to abe4a8601a)
Solutions
- Pass a plain object keyed by valid header names (no empty keys).
- Filter out empty-key entries before calling: `Object.fromEntries(Object.entries(h).filter(([k]) => k !== ''))`.
- If you have an array of values, map them to {key: value} pairs explicitly.
Example fix
// before
validateCustomHeaders({ '': 'no-name' }) // throws
validateCustomHeaders(['a','b']) // array, key '0' passes here but fails later
// after
validateCustomHeaders({ 'X-Trace-Id': 'a' }) Defensive patterns
Strategy: validation
Validate before calling
// Strip empty-key entries before validation
function dropEmptyKeys(headers) {
return Object.fromEntries(Object.entries(headers).filter(([k]) => typeof k === 'string' && k.length > 0))
} Type guard
function hasNoEmptyKeys(headers) {
return Object.keys(headers).every((k) => typeof k === 'string' && k.length > 0)
} Try / catch
try {
validateCustomHeaders(headers)
} catch (e) {
if (/key must be a non-empty string/i.test(e.message)) headers = dropEmptyKeys(headers)
else throw e
validateCustomHeaders(headers)
} Prevention
- Pass a plain object, never an array.
- Filter empty header names from user input at the form boundary.
- Catch key/value swaps at the UI (the field labeled 'name' should hold a name).
When it happens
Trigger: Header bag contains an empty-string key, or an array is passed whose entries have numeric-string keys (key '0' survives non-empty but later fails RFC7230_TOKEN), or a Map/object with non-string keys was used upstream.
Common situations: Caller passed an array of values instead of an object; empty header name from user input not filtered; key/value swap left the name blank.
Related errors
- Invalid headers: expected an object
- Invalid headers: too many entries (max ${MAX_HEADERS})
- Invalid header "${key}": key exceeds ${MAX_KEY_LENGTH} chars
- Invalid header "${key}": key contains illegal characters
- Invalid header "${key}": this header name is not allowed
AI-assisted analysis of FlowiseAI/Flowise@abe4a8601a (2026-08-12).
Data as JSON: /api/errors/f3700f6ed269b0b6.
Report an issue: GitHub.