{"record":{"id":"daf279587f79016b","repo":"PrefectHQ/fastmcp","slug":"invalid-first-argument-type-name-or-fn-daf279","errorCode":null,"errorMessage":"Invalid first argument: {type(name_or_fn)}","messagePattern":"Invalid first argument: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"fastmcp_slim/fastmcp/tools/function_tool.py","lineNumber":621,"sourceCode":"            run_in_thread=run_in_thread,\n        )\n        target = fn.__func__ if isinstance(fn, staticmethod | MethodType) else fn\n        cast(Any, target).__fastmcp__ = metadata\n        return fn\n\n    def decorator(fn: F, tool_name: str | None) -> F:\n        return attach_metadata(fn, tool_name)\n\n    if inspect.isroutine(name_or_fn):\n        return decorator(name_or_fn, name)\n    elif isinstance(name_or_fn, str):\n        if name is not None:\n            raise TypeError(\"Cannot specify name both as first argument and keyword\")\n        tool_name = name_or_fn\n    elif name_or_fn is None:\n        tool_name = name\n    else:\n        raise TypeError(f\"Invalid first argument: {type(name_or_fn)}\")\n\n    def wrapper(fn: F) -> F:\n        return decorator(fn, tool_name)\n\n    return wrapper\n","sourceCodeStart":603,"sourceCodeEnd":627,"githubUrl":"https://github.com/PrefectHQ/fastmcp/blob/1f021142978e0861cd910c8df4e8074bc7cf3978/fastmcp_slim/fastmcp/tools/function_tool.py#L603-L627","documentation":"The first positional argument of @tool must be a callable (direct decoration), a string (tool name), or None. Anything else (int, dict, function-like object that isn't a routine, etc.) falls through to this TypeError reporting the offending type.","triggerScenarios":"@tool(42), @tool(some_config_dict), @tool(instance) where instance is not a routine/string/None — any misuse of the decorator's first positional slot.","commonSituations":"Passing a configuration object or metadata as the first argument thinking it's the name; accidentally calling @tool(fn_result) instead of @tool; typos like @tool(name) where name is undefined-ish object.","solutions":["Pass a callable to decorate directly: @tool\\ndef fn(...)","Pass a string name: @tool(\"my_name\")","Pass nothing: @tool with keyword options only"],"exampleFix":"// before\n@tool({\"name\": \"x\"})\ndef fn(x: int) -> int: ...\n// after\n@tool(\"x\")\ndef fn(x: int) -> int: ...","handlingStrategy":"type-guard","validationCode":"def check_tool_first_arg(name_or_fn):\n    if name_or_fn is None or isinstance(name_or_fn, str):\n        return\n    if callable(name_or_fn):\n        return\n    raise TypeError(f'Invalid first argument: {type(name_or_fn)}')","typeGuard":"def is_valid_tool_first_arg(x) -> bool:\n    return x is None or isinstance(x, str) or (callable(x) and not isinstance(x, (int, dict, list)))","tryCatchPattern":"try:\n    tool = tool_decorator(x)\nexcept TypeError as e:\n    if 'Invalid first argument' in str(e):\n        tool = tool_decorator(name=x['name'])(fn)  # recover correct form","preventionTips":["Only pass a callable, a string, or nothing as the first decorator argument","Don't pass config dicts/metadata objects positionally to @tool","Check decorator usage examples in docs when adding options"],"tags":["python","decorators","api-misuse","argument-type"],"backgroundTag":"invalid-argument-type","analyzedSha":"1f021142978e0861cd910c8df4e8074bc7cf3978","analyzedAt":"2026-08-29T14:31:16.082Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}