huggingface/smolagents · error · TypeError
Attribute {attr} should have type {expected_type.__name__},
Error message
Attribute {attr} should have type {expected_type.__name__}, got {type(attr_value)} instead. What it means
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.
Source
Thrown at src/smolagents/tools.py:157
def __init_subclass__(cls, **kwargs):
super().__init_subclass__(**kwargs)
validate_after_init(cls)
def validate_arguments(self):
required_attributes = {
"description": str,
"name": str,
"inputs": dict,
"output_type": str,
}
# Validate class attributes
for attr, expected_type in required_attributes.items():
attr_value = getattr(self, attr, None)
if attr_value is None:
raise TypeError(f"You must set an attribute {attr}.")
if not isinstance(attr_value, expected_type):
raise TypeError(
f"Attribute {attr} should have type {expected_type.__name__}, got {type(attr_value)} instead."
)
# Validate optional output_schema attribute
output_schema = getattr(self, "output_schema", None)
if output_schema is not None and not isinstance(output_schema, dict):
raise TypeError(f"Attribute output_schema should have type dict, got {type(output_schema)} instead.")
# - Validate name
if not is_valid_name(self.name):
raise Exception(
f"Invalid Tool name '{self.name}': must be a valid Python identifier and not a reserved keyword"
)
# Validate inputs
for input_name, input_content in self.inputs.items():
assert isinstance(input_content, dict), f"Input '{input_name}' should be a dictionary."
assert "type" in input_content and "description" in input_content, (
f"Input '{input_name}' should have keys 'type' and 'description', has only {list(input_content.keys())}."View on GitHub (pinned to 30bb116109)
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
Example fix
# before
class MyTool(Tool):
inputs = ["query"] # wrong type
# after
class MyTool(Tool):
inputs = {"query": {"type": "string", "description": "search query"}} Defensive patterns
Strategy: type-guard
Validate before calling
REQUIRED = {"name": str, "description": str, "inputs": dict, "output_type": str}
def tool_types_ok(cls) -> bool:
return all(isinstance(getattr(cls, a, None), t) for a, t in REQUIRED.items()) Type guard
def tool_attributes_well_typed(cls) -> bool:
return all(isinstance(getattr(cls, a, None), t) for a, t in REQUIRED.items()) Try / catch
try:
MyTool()
except TypeError as e:
# message names attribute, expected and actual type
raise Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- {e}
- You must set an attribute {attr}.
- Attribute output_schema should have type dict, got {type(out
- Invalid Tool name '{self.name}': must be a valid Python iden
- Input '{input_name}': when type is a list, all elements must
AI-assisted analysis of huggingface/smolagents@30bb116109 (2026-08-28).
Data as JSON: /api/errors/49033b58d9fe3675.
Report an issue: GitHub.