{"record":{"id":"d821b822ca81148b","repo":"langchain-ai/deepagents","slug":"field-name-entries-must-be-strings-got-type","errorCode":null,"errorMessage":"`{field_name}` entries must be strings, got {type(entry).__name__} ({entry!r})","messagePattern":"`(.+?)` entries must be strings, got (.+?) \\((.+?)\\)","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"libs/deepagents/deepagents/profiles/harness/harness_profiles.py","lineNumber":854,"sourceCode":"        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\n\ndef _validate_config_middleware_string(entry: object, field_name: str) -> None:\n    \"\"\"Validate grammar of a string `excluded_middleware` entry.\n\n    Runs at `HarnessProfile` / `HarnessProfileConfig` construction so malformed","sourceCodeStart":836,"sourceCodeEnd":872,"githubUrl":"https://github.com/langchain-ai/deepagents/blob/a1af029e6e73cb17c36bff823d227747b28e91e1/libs/deepagents/deepagents/profiles/harness/harness_profiles.py#L836-L872","documentation":"After confirming the container type, _coerce_frozen_strset checks each entry is a str. A non-string element raises a TypeError naming the field, the element's type, and its repr. This keeps excluded tool/middleware sets strictly string-based.","triggerScenarios":"from_dict receiving excluded_tools/excluded_middleware containing non-str items, e.g. {\"excluded_tools\": [\"bash\", 42]} or enums/None mixed into the list.","commonSituations":"Configs generated by scripts appending raw IDs or enum members instead of tool-name strings; YAML lists where an entry parsed as a number or boolean (e.g. a tool literally named `no` becoming False in YAML).","solutions":["Cast each entry to str (or map enum members to their string names) before calling from_dict.","Quote entries in YAML that could parse as non-strings (e.g. 'no', 'on', numeric-looking names).","Filter or repair the list upstream so it contains only strings."],"exampleFix":"// before\nconfig = HarnessProfileConfig.from_dict({\"excluded_tools\": [\"bash\", 42]})\n// after\nconfig = HarnessProfileConfig.from_dict({\"excluded_tools\": [str(t) for t in [\"bash\", 42]]})","handlingStrategy":"type-guard","validationCode":"tools = data.get(\"excluded_tools\") or []\nif not all(isinstance(e, str) for e in tools):\n    data[\"excluded_tools\"] = [str(e) for e in tools]","typeGuard":"def is_str_list(value: object) -> TypeGuard[list[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 \"entries must be strings\" in str(e):\n        field = str(e).split('`')[1]\n        data[field] = [str(e2) for e2 in data[field]]\n        config = HarnessProfileConfig.from_dict(data)\n    else:\n        raise","preventionTips":["Map enum members to their string names before building exclusion lists.","Quote YAML entries that could parse as booleans or numbers ('no', '1').","Validate list element types at config-load boundaries."],"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"}