mem0ai/mem0 · error · ValueError
All header keys and values must be strings
Error message
All header keys and values must be strings
What it means
Raised by the Elasticsearch config's header validator when headers is a dict but at least one key or value is not a str. HTTP headers are string-to-string mappings; ints, bools, or None values pass the isinstance(headers, dict) check and then fail this per-item string check.
Source
Thrown at mem0/configs/vector_stores/elasticsearch.py:51
if not any([values.get("api_key"), (values.get("user") and values.get("password"))]):
raise ValueError("Either api_key or user/password must be provided")
return values
@model_validator(mode="before")
@classmethod
def validate_headers(cls, values: Dict[str, Any]) -> Dict[str, Any]:
"""Validate headers format and content"""
headers = values.get("headers")
if headers is not None:
# Check if headers is a dictionary
if not isinstance(headers, dict):
raise ValueError("headers must be a dictionary")
# Check if all keys and values are strings
for key, value in headers.items():
if not isinstance(key, str) or not isinstance(value, str):
raise ValueError("All header keys and values must be strings")
return values
@model_validator(mode="before")
@classmethod
def validate_extra_fields(cls, values: Dict[str, Any]) -> Dict[str, Any]:
allowed_fields = set(cls.model_fields.keys())
input_fields = set(values.keys())
extra_fields = input_fields - allowed_fields
if extra_fields:
raise ValueError(
f"Extra fields not allowed: {', '.join(extra_fields)}. "
f"Please input only the following fields: {', '.join(allowed_fields)}"
)
return values
model_config = ConfigDict(arbitrary_types_allowed=True)
View on GitHub (pinned to 001c235229)
Solutions
- Convert all header values to strings: headers={k: str(v) for k, v in headers.items()}
- Drop None values before passing headers: {k: v for k, v in headers.items() if v is not None}
- Quote scalar header values in YAML/JSON so loaders keep them strings
- Add a quick assert that all(k, v are str) in config-loading code
Example fix
# before
ElasticsearchConfig(host="h", api_key="k", headers={"X-Opaque-Id": 42})
# after
ElasticsearchConfig(host="h", api_key="k", headers={"X-Opaque-Id": "42"}) Defensive patterns
Strategy: type-guard
Validate before calling
def validate_es_header_types(cfg: dict) -> None:
h = cfg.get("headers")
if isinstance(h, dict):
bad = [k for k, v in h.items() if not isinstance(k, str) or not isinstance(v, str)]
if bad:
raise RuntimeError(f"Header keys/values must be str, bad entries: {bad}") Type guard
def headers_all_str(cfg: dict) -> bool:
h = cfg.get("headers")
return h is None or (isinstance(h, dict) and all(isinstance(k, str) and isinstance(v, str) for k, v in h.items())) Try / catch
from pydantic import ValidationError
try:
ElasticsearchConfig(**cfg)
except ValidationError as e:
if "keys and values must be strings" in str(e):
# str() the values and drop Nones, then retry
... Prevention
- Normalize headers: {k: str(v) for k, v in h.items() if v is not None}
- Quote scalars in YAML so they stay strings
- Unit-test config loaders for header typing
When it happens
Trigger: headers={"X-Retry": 3} (int value), headers={None: "v"} (non-str key), or headers={"flag": True}. Typically values injected from typed config sources (env ints, YAML booleans).
Common situations: YAML parsing 'on'/'off' into booleans used as header values; numeric settings passed through without str() conversion; None values from optional config fields not filtered out.
Related errors
- headers must be a dictionary
- Either cloud_id or host must be provided
- Either api_key or user/password must be provided
- Extra fields not allowed: {', '.join(extra_fields)}. Please
- Either 'password' must be provided or 'use_azure_credential'
AI-assisted analysis of mem0ai/mem0@001c235229 (2026-08-15).
Data as JSON: /api/errors/d2117cb909842cd6.
Report an issue: GitHub.