langchain-ai/deepagents · error · TypeError
`general_purpose_subagent` must be a mapping, got {type(valu
Error message
`general_purpose_subagent` must be a mapping, got {type(value).__name__} What it means
_coerce_general_purpose_subagent converts the general_purpose_subagent value during from_dict. None maps to no subagent, a Mapping is delegated to GeneralPurposeSubagentProfile.from_dict, and anything else raises a TypeError naming the actual type. This enforces the nested-profile schema.
Source
Thrown at libs/deepagents/deepagents/profiles/harness/harness_profiles.py:866
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:
if not isinstance(entry, str):
msg = f"`{field_name}` entries must be strings, got {type(entry).__name__} ({entry!r})"
raise TypeError(msg)
entries.append(entry)
return frozenset(entries)
def _coerce_general_purpose_subagent(value: object) -> GeneralPurposeSubagentProfile | None:
"""Validate and construct a `GeneralPurposeSubagentProfile` from a dict value."""
if value is None:
return None
if isinstance(value, Mapping):
return GeneralPurposeSubagentProfile.from_dict(cast("Mapping[str, Any]", value))
msg = f"`general_purpose_subagent` must be a mapping, got {type(value).__name__}"
raise TypeError(msg)
def _validate_config_middleware_string(entry: object, field_name: str) -> None:
"""Validate grammar of a string `excluded_middleware` entry.
Runs at `HarnessProfile` / `HarnessProfileConfig` construction so malformed
entries fail immediately rather than at assembly time. Checks:
- Entry is a non-empty string.
- Entry does not contain `:`. Class-path (`module:Class`) entries are
reserved for a future revision and rejected upfront so config files
don't accumulate ambiguous shapes.
- Entry does not start with `_`. Private middleware classes live outside
the public exclusion surface.
Scaffolding-class/name rejection and matched-something coverage are
deliberately NOT checked here — those need the fully assembled middleware
stack.View on GitHub (pinned to a1af029e6e)
Solutions
- Provide a mapping of GeneralPurposeSubagentProfile fields, e.g. {"model": ..., "prompt": ...}.
- Pass None to omit the general-purpose subagent entirely.
- If you already have a GeneralPurposeSubagentProfile, serialize it with its to_dict() first, then pass the dict.
Example fix
// before
config = HarnessProfileConfig.from_dict({"general_purpose_subagent": "default"})
// after
config = HarnessProfileConfig.from_dict({"general_purpose_subagent": {"model": "claude-sonnet-4-5", "prompt": "Research task"}}) Defensive patterns
Strategy: type-guard
Validate before calling
gp = data.get("general_purpose_subagent")
if gp is not None and not isinstance(gp, Mapping):
data["general_purpose_subagent"] = gp.to_dict() if hasattr(gp, "to_dict") else None Type guard
def is_gp_subagent_dict(value: object) -> TypeGuard[dict[str, Any] | None]:
return value is None or isinstance(value, Mapping) Try / catch
try:
config = HarnessProfileConfig.from_dict(data)
except TypeError as e:
if "general_purpose_subagent must be a mapping" in str(e):
data["general_purpose_subagent"] = data["general_purpose_subagent"].to_dict()
config = HarnessProfileConfig.from_dict(data)
else:
raise Prevention
- Pass a mapping (or None) for general_purpose_subagent — never a string shorthand or live object.
- Serialize existing GeneralPurposeSubagentProfile instances with to_dict() before nesting.
- Check nested blocks in YAML/JSON configs were not collapsed to scalars.
When it happens
Trigger: Calling HarnessProfileConfig.from_dict with general_purpose_subagent set to a string, list, or object, e.g. {"general_purpose_subagent": "default"} instead of a mapping of subagent profile fields.
Common situations: Configs written as a named string shorthand for a built-in subagent; passing an already-constructed GeneralPurposeSubagentProfile object into from_dict; YAML config where the nested block was collapsed to a scalar.
Related errors
- `{field_name}` must be str or None, got {type(value).__name_
- 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/30b58c8d34ed44d3.
Report an issue: GitHub.