PrefectHQ/fastmcp · warning · ValueError
Excluded headers must be lowercase
Error message
Excluded headers must be lowercase
What it means
get_http_headers(include, ...) builds a default set of lowercase excluded header names; when a custom include set is provided, FastMCP sanity-checks that every exclusion entry is already lowercase before doing case-sensitive set math. This ValueError is thrown for non-lowercase exclude entries, preventing subtle filtering bugs from HTTP header case-insensitivity.
Source
Thrown at fastmcp_slim/fastmcp/server/dependencies.py:585
"upgrade",
"te",
"keep-alive",
"expect",
"accept",
"authorization",
"cookie",
# Proxy-related headers
"proxy-authenticate",
"proxy-authorization",
"proxy-connection",
# MCP-related headers
"mcp-session-id",
}
if include:
exclude_headers -= {h.lower() for h in include}
# Sanity check: all entries must already be lowercase
if not all(h.lower() == h for h in exclude_headers):
raise ValueError("Excluded headers must be lowercase")
headers: dict[str, str] = {}
try:
source: Any = get_http_request().headers.items()
except RuntimeError:
# No live request: inside a background-task worker, fall back to the
# headers the task carried from its originating request (set by the
# tasks extension from the snapshot). Empty elsewhere.
task_headers = _background_task_headers.get()
if task_headers is None:
return {}
source = task_headers.items()
for name, value in source:
lower_name = name.lower()
if lower_name not in exclude_headers:
headers[lower_name] = str(value)
return headersView on GitHub (pinned to 1f02114297)
Solutions
- Pass header names in include/exclude entirely lowercase (e.g. 'authorization', not 'Authorization').
- Normalize with name.lower() before calling get_http_headers.
- HTTP headers are matched case-insensitively downstream, so lowercasing loses nothing.
Example fix
// before
get_http_headers(include={"Authorization"})
// after
get_http_headers(include={"authorization"}) Defensive patterns
Strategy: validation
Validate before calling
names = {"Authorization"}
assert all(h == h.lower() for h in names), "header names must be lowercase"
get_http_headers(include=names) Type guard
def all_lowercase(names: set[str]) -> bool:
return all(n == n.lower() for n in names) Try / catch
try:
headers = get_http_headers(include=my_headers)
except ValueError as e:
if "Excluded headers must be lowercase" in str(e):
headers = get_http_headers(include={h.lower() for h in my_headers})
else:
raise Prevention
- Always lowercase header names before passing them in
- Remember HTTP headers are case-insensitive
- Add a lint/test asserting lowercase header constants
When it happens
Trigger: Calling get_http_headers() while the computed exclusion set contains an entry with uppercase characters — i.e. the include parameter or an internal default contributed a mixed-case header name (e.g. 'Authorization').
Common situations: Passing include={'Authorization'} or similarly cased names to get_http_headers; copy-pasting HTTP header names in their canonical Capitalized form.
Related errors
- Expected integer, got {raw!r}
- Expected number, got {raw!r}
- Expected boolean, got {raw!r}
- Expected JSON {schema_type}, got {raw!r}
- The API key is empty
AI-assisted analysis of PrefectHQ/fastmcp@1f02114297 (2026-08-29).
Data as JSON: /api/errors/058905247be5cbf7.
Report an issue: GitHub.