{"record":{"id":"8cbc0c0f3a1267e6","repo":"langchain-ai/deepagents","slug":"ptc-list-entries-must-be-str-or-basetool","errorCode":null,"errorMessage":"ptc list entries must be str or BaseTool","messagePattern":"ptc list entries must be str or BaseTool","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"libs/partners/quickjs/langchain_quickjs/_ptc.py","lineNumber":97,"sourceCode":"        individual tool invocation.\n    \"\"\"\n    if isinstance(config, list):\n        explicit_tools: list[BaseTool] = []\n        allow_names: set[str] = set()\n        for entry in config:\n            if isinstance(entry, BaseTool):\n                if entry.name == _RESERVED_SUBAGENT_TASK_NAME:\n                    raise ValueError(_TASK_IN_PTC_MSG)\n                if entry.name != self_tool_name:\n                    explicit_tools.append(entry)\n                continue\n            if isinstance(entry, str):\n                if entry == _RESERVED_SUBAGENT_TASK_NAME:\n                    raise ValueError(_TASK_IN_PTC_MSG)\n                allow_names.add(entry)\n                continue\n            msg = \"ptc list entries must be str or BaseTool\"\n            raise TypeError(msg)\n        selected = [\n            *explicit_tools,\n            *[t for t in tools if t.name != self_tool_name and t.name in allow_names],\n        ]\n        deduped: list[BaseTool] = []\n        seen_names: set[str] = set()\n        for tool in selected:\n            if tool.name in seen_names:\n                continue\n            seen_names.add(tool.name)\n            deduped.append(tool)\n        selected = deduped\n        _raise_on_invalid_ptc_tools(selected)\n        return selected\n    msg = (\n        \"Unsupported `ptc` config type. \"\n        \"Use a list of tool names, list of BaseTool instances, or disable PTC.\"\n    )","sourceCodeStart":79,"sourceCodeEnd":115,"githubUrl":"https://github.com/langchain-ai/deepagents/blob/a1af029e6e73cb17c36bff823d227747b28e91e1/libs/partners/quickjs/langchain_quickjs/_ptc.py#L79-L115","documentation":"Within a list-form `ptc` config, every entry must be either a tool name string or a `BaseTool` instance; any other type raises TypeError. The list must remain unambiguous for name-based allowlisting.","triggerScenarios":"Passing a ptc list containing e.g. a dict, `None`, a callable, or a tuple — anything that is not `str` or `BaseTool` — to `filter_tools_for_ptc` (via agent `ptc` config).","commonSituations":"Passing `@tool`-decorated function objects (which are not BaseTool instances) instead of the resulting tool; passing tool-name/description dicts; JSON config values parsed into mixed types.","solutions":["Replace the offending entry with the tool's name string or its BaseTool instance","If passing decorated functions, use the returned BaseTool object, not the raw function","Normalize heterogeneous input: `[t.name if isinstance(t, BaseTool) else str(t) for t in items]` only for valid items"],"exampleFix":"# before\nptc=[my_tool, {\"name\": \"websearch\"}]\n# after\nptc=[my_tool, \"websearch\"]","handlingStrategy":"type-guard","validationCode":"bad = [x for x in ptc_list if not isinstance(x, (str, BaseTool))]\nif bad:\n    raise TypeError(f\"ptc entries must be str or BaseTool, got {bad!r}\")","typeGuard":"def is_valid_ptc_entry(x: object) -> TypeGuard[Union[str, BaseTool]]:\n    return isinstance(x, (str, BaseTool))","tryCatchPattern":"try:\n    selected = filter_tools_for_ptc(tools, ptc_list)\nexcept TypeError as e:\n    if \"str or BaseTool\" in str(e):\n        ptc_list = [x.name if isinstance(x, BaseTool) else str(x) for x in ptc_list if isinstance(x, (str, BaseTool))]\n        selected = filter_tools_for_ptc(tools, ptc_list)\n    else:\n        raise","preventionTips":["Use the BaseTool returned by @tool decorators, not the decorated function","Normalize configs to strings as early as possible in the load path","Add runtime type checks where ptc config crosses a serialization boundary (JSON/YAML)"],"tags":["ptc","type-error","tools","validation"],"backgroundTag":"invalid-argument-type","analyzedSha":"a1af029e6e73cb17c36bff823d227747b28e91e1","analyzedAt":"2026-08-29T11:43:24.718Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}