langchain-ai/deepagents · error · TypeError
`{field_name}` must be a mapping, got {type(value).__name__}
Error message
`{field_name}` must be a mapping, got {type(value).__name__} What it means
_coerce_str_mapping validates tool_description_overrides-style fields. If the value is not a Mapping (and not None), a TypeError is raised naming the field and the actual type. This ensures override tables are dict-shaped before per-key string validation.
Source
Thrown at libs/deepagents/deepagents/profiles/harness/harness_profiles.py:833
Derived from the dataclass fields for drift-free parity with the class.
"""
def _coerce_str_or_none(value: object, field_name: str) -> str | None:
"""Validate that `value` is a string or `None` for dict-loaded string fields."""
if value is None or isinstance(value, str):
return value
msg = f"`{field_name}` must be str or None, got {type(value).__name__}"
raise TypeError(msg)
def _coerce_str_mapping(value: object, field_name: str) -> dict[str, str]:
"""Validate that `value` is a `str -> str` mapping (or `None`) and return a plain dict."""
if value is None:
return {}
if not isinstance(value, Mapping):
msg = f"`{field_name}` must be a mapping, got {type(value).__name__}"
raise TypeError(msg)
out: dict[str, str] = {}
for key, val in value.items():
if not isinstance(key, str) or not isinstance(val, str):
msg = f"`{field_name}` keys and values must be strings"
raise TypeError(msg)
out[key] = val
return out
def _coerce_frozen_strset(value: object, field_name: str) -> frozenset[str]:
"""Validate that `value` is an iterable of strings (or `None`)."""
if value is None:
return frozenset()
if not isinstance(value, (list, tuple, set, frozenset)):
msg = f"`{field_name}` must be a list/set of strings, got {type(value).__name__}"
raise TypeError(msg)
entries: list[str] = []
for entry in value:View on GitHub (pinned to a1af029e6e)
Solutions
- Pass a plain dict {str: str} for the field.
- Convert list-of-pairs input with dict(pairs) before the call.
- Fix the config file so the field is a mapping (key: value), not a string or array.
Example fix
// before
config = HarnessProfileConfig.from_dict({"tool_description_overrides": [("bash", "Run shell")]} )
// after
config = HarnessProfileConfig.from_dict({"tool_description_overrides": {"bash": "Run shell"}}) Defensive patterns
Strategy: type-guard
Validate before calling
overrides = data.get("tool_description_overrides")
if overrides is not None and not isinstance(overrides, Mapping):
data["tool_description_overrides"] = dict(overrides) if isinstance(overrides, list) else {} Type guard
def is_str_mapping(value: object) -> TypeGuard[dict[str, str]]:
return isinstance(value, Mapping) and all(
isinstance(k, str) and isinstance(v, str) for k, v in value.items()
) Try / catch
try:
config = HarnessProfileConfig.from_dict(data)
except TypeError as e:
if "must be a mapping" in str(e):
field = str(e).split('`')[1]
data[field] = dict(data[field])
config = HarnessProfileConfig.from_dict(data)
else:
raise Prevention
- Build override tables as dicts, never lists of tuples.
- Check that config files use key: value mappings for override fields.
- Run is_str_mapping on any externally sourced override table before use.
When it happens
Trigger: Passing a list of pairs, a string, or a scalar where a str->str mapping is expected — e.g. from_dict({"tool_description_overrides": [("bash", "Run bash")]}), to_dict on a profile with a corrupted field, or from_harness_profile with a non-mapping override.
Common situations: Building overrides as a list of tuples in Python instead of a dict; YAML/JSON configs where the mapping was accidentally flattened to a string; merging override sources that produced a non-dict value.
Related errors
- `{field_name}` keys and values must be strings
- interpreter_ptc must be False, 'safe', 'all', or a list of t
- max_retries must be an int, got {type(max_retries).__name__}
- stream_output_is_visible must be a bool, got {type(stream_ou
- context.{key} must be a string or null, got {type(value).__n
AI-assisted analysis of langchain-ai/deepagents@a1af029e6e (2026-08-29).
Data as JSON: /api/errors/980e325998adf068.
Report an issue: GitHub.