unclecode/crawl4ai · warning · ValueError
invalid webhook header name: {name!r}
Error message
invalid webhook header name: {name!r} What it means
ValueError from sanitize_webhook_headers when a header name is not a string or fails the _WEBHOOK_HEADER_NAME regex (valid RFC 7230 token characters only). The offending name is echoed in quotes for debugging.
Source
Thrown at deploy/docker/webhook.py:72
_WEBHOOK_DENY_HEADERS = {
"host", "content-length", "transfer-encoding", "connection",
"content-type", "proxy-authorization", "authorization", "cookie",
"expect", "upgrade", "te", "trailer",
}
_MAX_WEBHOOK_HEADERS = 20
_MAX_WEBHOOK_HEADER_VALUE = 2048
def sanitize_webhook_headers(headers: Optional[Dict[str, str]]) -> Dict[str, str]:
"""Validate user-supplied webhook headers; raise ValueError on any bad one."""
if not headers:
return {}
if len(headers) > _MAX_WEBHOOK_HEADERS:
raise ValueError("too many webhook headers")
clean: Dict[str, str] = {}
for name, value in headers.items():
if not isinstance(name, str) or not _WEBHOOK_HEADER_NAME.match(name):
raise ValueError(f"invalid webhook header name: {name!r}")
if name.lower() in _WEBHOOK_DENY_HEADERS:
raise ValueError(f"webhook header not allowed: {name}")
sval = str(value)
if len(sval) > _MAX_WEBHOOK_HEADER_VALUE or any(c in sval for c in "\r\n\x00"):
raise ValueError(f"invalid value for webhook header {name}")
clean[name] = sval
return clean
class WebhookDeliveryService:
"""Handles webhook delivery with exponential backoff retry logic."""
def __init__(self, config: Dict):
"""
Initialize the webhook delivery service.
Args:
config: Application configuration dictionary containing webhook settingsView on GitHub (pinned to 7e80152142)
Solutions
- Use standard token names: letters, digits, and hyphens (e.g. X-Custom-Header)
- Sanitize on the client: re.sub(r'[^A-Za-z0-9_-]', '-', name) before sending
- Assert len(name) > 0 and name == name.strip() when generating names dynamically
Example fix
# before
"headers": {"X Crawl Source": "batch-1"}
# after
"headers": {"X-Crawl-Source": "batch-1"} Defensive patterns
Strategy: validation
Validate before calling
import re
TOKEN = re.compile(r"^[A-Za-z0-9!#$%&'*+.^_`|~-]+$")
def valid_header_names(headers: dict) -> bool:
return all(isinstance(k, str) and TOKEN.match(k) for k in headers) Type guard
def is_valid_webhook_header_set(h) -> bool:
return (isinstance(h, dict) and len(h) <= 20
and all(isinstance(k, str) and TOKEN.match(k) for k in h)) Try / catch
try:
sanitize_webhook_headers(headers)
except ValueError as e:
if "header name" in str(e):
headers = {re.sub(r"[^A-Za-z0-9-]", "-", k): v for k, v in headers.items()} Prevention
- Generate header names from a fixed vocabulary (X-*) rather than free-form text
- Strip whitespace and reject empty keys when building header dicts programmatically
When it happens
Trigger: A webhook headers key containing spaces ('X My Header'), non-ASCII, brackets, or empty string; or a non-str key (int, None) coming from JSON with odd keys or programmatic dict building.
Common situations: Client copies browser request headers including formatting quirks; using 'X-Custom Header:' style labels; keys generated from f-strings with stray whitespace or newlines.
Related errors
- webhook header not allowed: {name}
- URL must have a valid hostname
- too many webhook headers
- invalid value for webhook header {name}
- Hook '{hook_name}' must be a callable function, got {type(ho
AI-assisted analysis of unclecode/crawl4ai@7e80152142 (2026-08-14).
Data as JSON: /api/errors/bddeb81890b97f15.
Report an issue: GitHub.