{"record":{"id":"49033b58d9fe3675","repo":"huggingface/smolagents","slug":"attribute-attr-should-have-type-expected-type","errorCode":null,"errorMessage":"Attribute {attr} should have type {expected_type.__name__}, got {type(attr_value)} instead.","messagePattern":"Attribute (.+?) should have type (.+?), got (.+?) instead\\.","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"src/smolagents/tools.py","lineNumber":157,"sourceCode":"\n    def __init_subclass__(cls, **kwargs):\n        super().__init_subclass__(**kwargs)\n        validate_after_init(cls)\n\n    def validate_arguments(self):\n        required_attributes = {\n            \"description\": str,\n            \"name\": str,\n            \"inputs\": dict,\n            \"output_type\": str,\n        }\n        # Validate class attributes\n        for attr, expected_type in required_attributes.items():\n            attr_value = getattr(self, attr, None)\n            if attr_value is None:\n                raise TypeError(f\"You must set an attribute {attr}.\")\n            if not isinstance(attr_value, expected_type):\n                raise TypeError(\n                    f\"Attribute {attr} should have type {expected_type.__name__}, got {type(attr_value)} instead.\"\n                )\n\n        # Validate optional output_schema attribute\n        output_schema = getattr(self, \"output_schema\", None)\n        if output_schema is not None and not isinstance(output_schema, dict):\n            raise TypeError(f\"Attribute output_schema should have type dict, got {type(output_schema)} instead.\")\n\n        # - Validate name\n        if not is_valid_name(self.name):\n            raise Exception(\n                f\"Invalid Tool name '{self.name}': must be a valid Python identifier and not a reserved keyword\"\n            )\n        # Validate inputs\n        for input_name, input_content in self.inputs.items():\n            assert isinstance(input_content, dict), f\"Input '{input_name}' should be a dictionary.\"\n            assert \"type\" in input_content and \"description\" in input_content, (\n                f\"Input '{input_name}' should have keys 'type' and 'description', has only {list(input_content.keys())}.\"","sourceCodeStart":139,"sourceCodeEnd":175,"githubUrl":"https://github.com/huggingface/smolagents/blob/30bb1161095dbae2271e6bc3cc4c219cc3897a57/src/smolagents/tools.py#L139-L175","documentation":"validate_arguments checks isinstance for each required Tool class attribute. If the attribute exists but has the wrong type (e.g. inputs is a list, output_type is not a str, description is an int), it raises TypeError naming the expected type and the actual type. This is a type-contract check, not a missing-attribute check.","triggerScenarios":"Defining a Tool subclass where name/description/output_type is not a str, or inputs is not a dict (e.g. inputs = [\"query\"]); raised at instantiation through new_init → validate_arguments.","commonSituations":"Setting inputs to a list of names or a JSON string instead of a dict of {name: {type, description}}; assigning non-string constants (enum, object) to name/description; mutating class attributes after class definition with wrong-typed values.","solutions":["Change the attribute to the declared type shown in the message (str for name/description/output_type, dict for inputs)","Structure inputs as {param_name: {\"type\": ..., \"description\": ...}}","Add a quick unit test that instantiates the tool to catch contract violations early"],"exampleFix":"# before\nclass MyTool(Tool):\n    inputs = [\"query\"]  # wrong type\n\n# after\nclass MyTool(Tool):\n    inputs = {\"query\": {\"type\": \"string\", \"description\": \"search query\"}}","handlingStrategy":"type-guard","validationCode":"REQUIRED = {\"name\": str, \"description\": str, \"inputs\": dict, \"output_type\": str}\ndef tool_types_ok(cls) -> bool:\n    return all(isinstance(getattr(cls, a, None), t) for a, t in REQUIRED.items())","typeGuard":"def tool_attributes_well_typed(cls) -> bool:\n    return all(isinstance(getattr(cls, a, None), t) for a, t in REQUIRED.items())","tryCatchPattern":"try:\n    MyTool()\nexcept TypeError as e:\n    # message names attribute, expected and actual type\n    raise","preventionTips":["inputs must be a dict of dicts; never a list or JSON string","Keep name/description/output_type as plain str literals","Type-check tool classes in CI tests"],"tags":["smolagents","tool","type-error","validation"],"backgroundTag":"attribute-type-mismatch","analyzedSha":"30bb1161095dbae2271e6bc3cc4c219cc3897a57","analyzedAt":"2026-08-28T18:52:54.169Z","schemaVersion":2},"datasetVersion":"2026-08-28T21:17:43.275Z"}