{"record":{"id":"4f4da239aff0e3bc","repo":"langchain-ai/deepagents","slug":"field-name-must-be-a-list-set-of-strings-got","errorCode":null,"errorMessage":"`{field_name}` must be a list/set of strings, got {type(value).__name__}","messagePattern":"`(.+?)` must be a list/set of strings, got (.+?)","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"libs/deepagents/deepagents/profiles/harness/harness_profiles.py","lineNumber":849,"sourceCode":"    if not isinstance(value, Mapping):\n        msg = f\"`{field_name}` must be a mapping, got {type(value).__name__}\"\n        raise TypeError(msg)\n    out: dict[str, str] = {}\n    for key, val in value.items():\n        if not isinstance(key, str) or not isinstance(val, str):\n            msg = f\"`{field_name}` keys and values must be strings\"\n            raise TypeError(msg)\n        out[key] = val\n    return out\n\n\ndef _coerce_frozen_strset(value: object, field_name: str) -> frozenset[str]:\n    \"\"\"Validate that `value` is an iterable of strings (or `None`).\"\"\"\n    if value is None:\n        return frozenset()\n    if not isinstance(value, (list, tuple, set, frozenset)):\n        msg = f\"`{field_name}` must be a list/set of strings, got {type(value).__name__}\"\n        raise TypeError(msg)\n    entries: list[str] = []\n    for entry in value:\n        if not isinstance(entry, str):\n            msg = f\"`{field_name}` entries must be strings, got {type(entry).__name__} ({entry!r})\"\n            raise TypeError(msg)\n        entries.append(entry)\n    return frozenset(entries)\n\n\ndef _coerce_general_purpose_subagent(value: object) -> GeneralPurposeSubagentProfile | None:\n    \"\"\"Validate and construct a `GeneralPurposeSubagentProfile` from a dict value.\"\"\"\n    if value is None:\n        return None\n    if isinstance(value, Mapping):\n        return GeneralPurposeSubagentProfile.from_dict(cast(\"Mapping[str, Any]\", value))\n    msg = f\"`general_purpose_subagent` must be a mapping, got {type(value).__name__}\"\n    raise TypeError(msg)\n","sourceCodeStart":831,"sourceCodeEnd":867,"githubUrl":"https://github.com/langchain-ai/deepagents/blob/a1af029e6e73cb17c36bff823d227747b28e91e1/libs/deepagents/deepagents/profiles/harness/harness_profiles.py#L831-L867","documentation":"_coerce_frozen_strset validates set-typed fields (excluded_tools, excluded_middleware) loaded from dicts. If the value is not a list, tuple, set, or frozenset (and not None), a TypeError is raised naming the field and its actual type. The result is normalized to a frozenset of strings.","triggerScenarios":"Calling HarnessProfileConfig.from_dict with e.g. {\"excluded_tools\": \"bash\"} (bare string instead of a list) or {\"excluded_tools\": {\"bash\": true}} (dict).","commonSituations":"YAML/JSON configs where a single excluded tool was written as a plain string instead of a one-element list; string-joined values like \"bash,git\"; config builders assigning dict membership maps.","solutions":["Wrap the value in a list: [\"bash\"] instead of \"bash\".","Split comma-joined strings before passing: value.split(\",\").","Use a set/frozenset directly if building programmatically."],"exampleFix":"// before\nconfig = HarnessProfileConfig.from_dict({\"excluded_tools\": \"bash\"})\n// after\nconfig = HarnessProfileConfig.from_dict({\"excluded_tools\": [\"bash\"]})","handlingStrategy":"type-guard","validationCode":"tools = data.get(\"excluded_tools\")\nif isinstance(tools, str):\n    data[\"excluded_tools\"] = tools.split(\",\") if \",\" in tools else [tools]","typeGuard":"def is_str_iterable(value: object) -> TypeGuard[list[str] | set[str] | tuple[str, ...] | frozenset[str]]:\n    return isinstance(value, (list, tuple, set, frozenset)) and all(isinstance(e, str) for e in value)","tryCatchPattern":"try:\n    config = HarnessProfileConfig.from_dict(data)\nexcept TypeError as e:\n    if \"must be a list/set of strings\" in str(e):\n        field = str(e).split('`')[1]\n        data[field] = [data[field]]\n        config = HarnessProfileConfig.from_dict(data)\n    else:\n        raise","preventionTips":["Always write exclusion sets as lists in config files, even for one entry.","Never pass a bare string where a set field is expected.","Normalize comma-joined values to lists before from_dict."],"tags":["python","type-error","validation","set"],"backgroundTag":"type-validation-failed","analyzedSha":"a1af029e6e73cb17c36bff823d227747b28e91e1","analyzedAt":"2026-08-29T11:43:24.718Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}