{"record":{"id":"f5a748db4ca2c9fa","repo":"PrefectHQ/fastmcp","slug":"cannot-specify-both-a-name-as-first-argument-and-a-f5a748","errorCode":null,"errorMessage":"Cannot specify both a name as first argument and as keyword argument. Use either @tool('{name_or_fn}') or @tool(name='{name}'), not both.","messagePattern":"Cannot specify both a name as first argument and as keyword argument\\. Use either @tool\\('(.+?)'\\) or @tool\\(name='(.+?)'\\), not both\\.","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"fastmcp_slim/fastmcp/server/providers/local_provider/decorators/tools.py","lineNumber":329,"sourceCode":"                meta=meta,\n                task=task,\n                timeout=timeout,\n                auth=auth,\n                enabled=enabled,\n                run_in_thread=run_in_thread,\n            )\n            target = fn.__func__ if hasattr(fn, \"__func__\") else fn\n            target.__fastmcp__ = metadata  # type: ignore[attr-defined]  # ty:ignore[unresolved-attribute]\n            self.add_tool(fn)\n            return fn\n\n        if inspect.isroutine(name_or_fn):\n            return decorate_and_register(name_or_fn, name)\n\n        elif isinstance(name_or_fn, str):\n            # Case 3: @tool(\"custom_name\") - name passed as first argument\n            if name is not None:\n                raise TypeError(\n                    \"Cannot specify both a name as first argument and as keyword argument. \"\n                    f\"Use either @tool('{name_or_fn}') or @tool(name='{name}'), not both.\"\n                )\n            tool_name = name_or_fn\n        elif name_or_fn is None:\n            # Case 4: @tool() or @tool(name=\"something\") - use keyword name\n            tool_name = name\n        else:\n            raise TypeError(\n                f\"First argument to @tool must be a function, string, or None, got {type(name_or_fn)}\"\n            )\n\n        # Return partial for cases where we need to wait for the function\n        return partial(\n            self.tool,\n            name=tool_name,\n            version=version,\n            title=title,","sourceCodeStart":311,"sourceCodeEnd":347,"githubUrl":"https://github.com/PrefectHQ/fastmcp/blob/1f021142978e0861cd910c8df4e8074bc7cf3978/fastmcp_slim/fastmcp/server/providers/local_provider/decorators/tools.py#L311-L347","documentation":"@tool accepts a tool name either as the first positional string argument or via the name keyword, but not both. Passing both is ambiguous, so FastMCP raises a TypeError explaining the two supported forms.","triggerScenarios":"Calling @tool('my_tool', name='my_tool') or @tool('custom', name='other') — a string as the first argument together with a non-None name keyword.","commonSituations":"Refactoring from @tool(name='x') to @tool('x') (or vice versa) and leaving both in place; IDE auto-completes adding a duplicate name argument; copy-paste from two examples.","solutions":["Keep only one: either @tool('name') or @tool(name='name').","If the two names differ, decide which one is intended and remove the other; the description-style first argument does not exist — only name is positional."],"exampleFix":"// before\n@tool('my_tool', name='my_tool')\ndef my_tool(x: int) -> str:\n    ...\n\n// after\n@tool('my_tool')\ndef my_tool(x: int) -> str:\n    ...","handlingStrategy":"validation","validationCode":"def check_tool_args(*args, **kwargs):\n    positional_names = [a for a in args if isinstance(a, str)]\n    if positional_names and kwargs.get('name') is not None:\n        raise TypeError('pass the tool name either positionally or via name=, not both')\n\ncheck_tool_args('my_tool', name='my_tool')  # would raise","typeGuard":"def name_conflict(first_arg, name) -> bool:\n    return isinstance(first_arg, str) and name is not None","tryCatchPattern":"try:\n    register_tools()\nexcept TypeError as e:\n    if 'both a name as first argument and as keyword' in str(e):\n        logging.error('remove the duplicate tool name argument')\n    raise","preventionTips":["Pick one convention repo-wide, e.g. always @tool('name').","Never pass name= together with a positional string.","Let linters/review flag decorator calls with both positional string and name=."],"tags":["python","fastmcp","tools","api-misuse"],"backgroundTag":"duplicate-argument-conflict","analyzedSha":"1f021142978e0861cd910c8df4e8074bc7cf3978","analyzedAt":"2026-08-29T14:31:16.082Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}