huggingface/smolagents · error · TypeError
Argument has type ' ' but should be
Error message
Argument {key} has type '{actual_type}' but should be '{tool.inputs[key]['type']}' What it means
Raised by smolagents' validate_tool_arguments when an argument passed to a tool does not match the JSON Schema type declared in the tool's inputs definition. It is the library's pre-execution guard so that tool forward() methods receive correctly typed values. Integer values are accepted where 'number' is expected, and 'any' or nullable schemas bypass the check.
Solutions
- Fix the arguments to match the declared type (e.g., convert '5' to 5 before calling the tool)
- Adjust the tool's inputs declaration to the type actually received, or set 'type': 'any' / 'nullable': True where appropriate
- If a model keeps emitting wrong types, tighten the tool description or prompt so the model produces correctly typed JSON
- For integer-tolerant float inputs, note ints are allowed for 'number' but not vice versa; cast in your wrapper
Example fix
# before
tool = Tool(name='add', inputs={'a': {'type': 'integer'}}, ...)
tool(a='5') # TypeError
# after
tool(a=int('5'))
# or declare: inputs={'a': {'type': 'any'}} Defensive patterns
Strategy: validation
Validate before calling
import json
def validate_args(tool, arguments):
type_map = {str: 'string', int: 'integer', float: 'number', bool: 'boolean', list: 'array', dict: 'object'}
for key, schema in tool.inputs.items():
if key in arguments and isinstance(schema.get('type'), str):
expected = schema['type']
if expected == 'any':
continue
actual = type_map.get(type(arguments[key]))
if actual and actual != expected and not (actual == 'integer' and expected == 'number'):
raise ValueError(f'{key}: expected {expected}, got {actual}')
return arguments Type guard
def args_match(tool, arguments: dict) -> bool:
tm = {str: 'string', int: 'integer', float: 'number', bool: 'boolean', list: 'array', dict: 'object'}
return all(
s.get('type') == 'any' or tm.get(type(arguments.get(k))) == s.get('type')
or (tm.get(type(arguments.get(k))) == 'integer' and s.get('type') == 'number')
for k, s in tool.inputs.items() if k in arguments
) Try / catch
try:
result = tool(**arguments)
except TypeError as e:
if 'has type' in str(e):
# coerce types from the message and retry, or log and surface to the model
raise Prevention
- Declare tool input types precisely and match them to forward() annotations
- Test each tool with representative argument dicts
- Mark flexible inputs as 'any' or 'nullable' deliberately
When it happens
Trigger: Calling a Tool (or an agent making a tool call) with, e.g., a string '5' where inputs declare {'type': 'integer'}, or a dict where 'array' is declared. Also triggered by argument keys not present in the tool's inputs whose type cannot be validated.
Common situations: LLM models returning numbers as strings, booleans as 'true', or lists as comma-separated strings; mismatch between the tool author's declared input types and what the model actually emits; custom tools with hand-written input schemas that don't match the Python signatures.
Related errors
- Argument has type ' ' but should be
- Argument is required
- Attribute output_schema should have type dict, got
- Error while parsing tool call from model output
- If you want to return an answer, please do not perform any…
AI-assisted analysis of huggingface/smolagents@30bb116109 (2026-08-28).
Data as JSON: /api/errors/c8554309806d8b1e.
Report an issue: GitHub.
Appendix: source
Thrown at src/smolagents/tools.py:1402
"""
if isinstance(arguments, dict):
for key, value in arguments.items():
if key not in tool.inputs:
raise ValueError(f"Argument {key} is not in the tool's input schema")
actual_type = _get_json_schema_type(type(value))["type"]
expected_type = tool.inputs[key]["type"]
expected_type_is_nullable = tool.inputs[key].get("nullable", False)
# Type is valid if it matches, is "any", or is null for nullable parameters
if (
(actual_type != expected_type if isinstance(expected_type, str) else actual_type not in expected_type)
and expected_type != "any"
and not (actual_type == "null" and expected_type_is_nullable)
):
if actual_type == "integer" and expected_type == "number":
continue
raise TypeError(f"Argument {key} has type '{actual_type}' but should be '{tool.inputs[key]['type']}'")
for key, schema in tool.inputs.items():
key_is_nullable = schema.get("nullable", False)
if key not in arguments and not key_is_nullable:
raise ValueError(f"Argument {key} is required")
return None
else:
expected_type = list(tool.inputs.values())[0]["type"]
if _get_json_schema_type(type(arguments))["type"] != expected_type and not expected_type == "any":
raise TypeError(f"Argument has type '{type(arguments).__name__}' but should be '{expected_type}'")
__all__ = [
"AUTHORIZED_TYPES",
"Tool",
"tool",
"load_tool",
"launch_gradio_demo",View on GitHub (pinned to 30bb116109)