deepset-ai/haystack · error · TypeError
The parameter 'http_client_kwargs' must be a dictionary.
Error message
The parameter 'http_client_kwargs' must be a dictionary.
What it means
TypeError raised by `init_http_client` when the http_client_kwargs parameter is truthy but not a dict. This helper builds an httpx (async) client and requires keyword arguments as a mapping so it can copy and post-process them (e.g. converting a 'limits' dict to httpx.Limits).
Source
Thrown at haystack/utils/http_client.py:35
) -> httpx.AsyncClient | None: ...
def init_http_client(
http_client_kwargs: dict[str, Any] | None = None, async_client: bool = False
) -> httpx.Client | httpx.AsyncClient | None:
"""
Initialize an httpx client based on the http_client_kwargs.
:param http_client_kwargs:
The kwargs to pass to the httpx client.
:param async_client:
Whether to initialize an async client.
:returns:
A httpx client or an async httpx client.
"""
if not http_client_kwargs:
return None
if not isinstance(http_client_kwargs, dict):
raise TypeError("The parameter 'http_client_kwargs' must be a dictionary.")
# Create a copy to avoid modifying the original dict
processed_kwargs = http_client_kwargs.copy()
# Handle limits parameter - convert dict to httpx.Limits object if needed
if "limits" in processed_kwargs and isinstance(processed_kwargs["limits"], dict):
limits_dict = processed_kwargs["limits"]
processed_kwargs["limits"] = httpx.Limits(**limits_dict)
if async_client:
return httpx.AsyncClient(**processed_kwargs)
return httpx.Client(**processed_kwargs)
View on GitHub (pinned to e318778c9b)
Solutions
- Pass http_client_kwargs as a dict, e.g. {'timeout': 10} or {'limits': {'max_connections': 10}}
- If you already have an httpx.Limits object, pass it inside the dict: {'limits': my_limits}
- Falsiness is allowed: pass None or {} to skip client creation entirely
Example fix
// before
client = init_http_client(http_client_kwargs=httpx.Limits(max_connections=5))
// after
client = init_http_client(http_client_kwargs={"limits": {"max_connections": 5}}) Defensive patterns
Strategy: type-guard
Validate before calling
def validate_client_kwargs(kwargs):
if kwargs is not None and not isinstance(kwargs, dict):
raise TypeError("http_client_kwargs must be a dict or None") Type guard
def is_valid_http_client_kwargs(v) -> bool:
return v is None or isinstance(v, dict) Try / catch
try:
client = init_http_client(http_client_kwargs=kwargs)
except TypeError as e:
log.warning("Bad http_client_kwargs: %s; using defaults", e)
client = None Prevention
- Always pass a dict literal: {'timeout': 10, 'limits': {...}}
- Never pass httpx.Limits/Timeout objects directly as http_client_kwargs
- Load client config from JSON/dict sources, not strings or custom objects
When it happens
Trigger: Passing http_client_kwargs as a string, list, object (e.g. an httpx.Limits instance directly), or dataclass instead of a dict to components/utils that call init_http_client, e.g. http_client_kwargs="timeout=5" or http_client_kwargs=httpx.Limits(...).
Common situations: Misreading the API and passing an httpx.Limits or httpx.Timeout object directly; passing JSON-serialized config strings; wiring a component's kwargs attribute to the wrong type.
Understand the failure class
Background: Invalid argument type errors: "must be of type string", "expected X, got Y", and ERR_INVALID_ARG_TYPE explained — this error's family across 15 libraries.
Related errors
- PythonCodeSplitter only works with text documents (str conte
- All separators must be strings.
- The following tool names are not valid: {invalid_tool_names}
- user_prompt must define exactly one message block, found {le
- user_prompt message block must have role 'user', found role
AI-assisted analysis of deepset-ai/haystack@e318778c9b (2026-08-30).
Data as JSON: /api/errors/8296fa3372be9efa.
Report an issue: GitHub.