{"record":{"id":"e909c486560e6d0c","repo":"PrefectHQ/fastmcp","slug":"cannot-specify-both-a-name-as-first-argument-and-a","errorCode":null,"errorMessage":"Cannot specify both a name as first argument and as keyword argument.","messagePattern":"Cannot specify both a name as first argument and as keyword argument\\.","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"fastmcp_slim/fastmcp/apps/app.py","lineNumber":126,"sourceCode":"\n        raise ValueError(f\"Cannot resolve tool reference: {fn!r}\")\n\n    return _resolve_tool_ref\n\n\ndef _dispatch_decorator(\n    name_or_fn: str | AnyFunction | None,\n    name: str | None,\n    register: Callable[[Any, str | None], Any],\n    decorator_name: str,\n) -> Any:\n    \"\"\"Shared dispatch logic for @app.tool() and @app.ui() calling patterns.\"\"\"\n    if inspect.isroutine(name_or_fn):\n        return register(name_or_fn, name)\n\n    if isinstance(name_or_fn, str):\n        if name is not None:\n            raise TypeError(\n                \"Cannot specify both a name as first argument and as keyword argument.\"\n            )\n        tool_name: str | None = name_or_fn\n    elif name_or_fn is None:\n        tool_name = name\n    else:\n        raise TypeError(\n            f\"First argument to @{decorator_name} must be a function, string, or None, \"\n            f\"got {type(name_or_fn)}\"\n        )\n\n    def decorator(fn: F) -> F:\n        return register(fn, tool_name)\n\n    return decorator\n\n\n# ---------------------------------------------------------------------------","sourceCodeStart":108,"sourceCodeEnd":144,"githubUrl":"https://github.com/PrefectHQ/fastmcp/blob/1f021142978e0861cd910c8df4e8074bc7cf3978/fastmcp_slim/fastmcp/apps/app.py#L108-L144","documentation":"The shared @app.tool() / @app.ui() decorator accepts a tool name either as the first positional argument or as the `name` keyword — but not both. If a string is passed positionally and a `name=` keyword is also supplied, this TypeError is raised because the intent is ambiguous.","triggerScenarios":"Calling `@app.tool(\"my_name\", name=\"other_name\")` or the equivalent with app.ui — a positional string name plus a keyword name.","commonSituations":"Refactoring from keyword style to positional (or vice versa) and leaving both in place; merging code changes that each added a name; copy-pasting decorator examples.","solutions":["Keep only one of the two: remove the keyword `name=` if a positional string is given.","If both names were intentional (e.g. UI name differs), pass the intended one and register the other explicitly.","Use @app.tool() with no args and rely on the function __name__ when no custom name is needed."],"exampleFix":"// before\n@app.tool(\"upload_file\", name=\"upload\")\ndef upload_file(...): ...\n// after\n@app.tool(\"upload\")\ndef upload_file(...): ...","handlingStrategy":"validation","validationCode":"def check_tool_decorator_args(name_or_fn, name):\n    if isinstance(name_or_fn, str) and name is not None:\n        raise TypeError(\"Provide the tool name either positionally or as name=, not both\")","typeGuard":"def has_conflicting_names(name_or_fn, name) -> bool:\n    return isinstance(name_or_fn, str) and name is not None","tryCatchPattern":"try:\n    deco = app.tool(\"upload\", name=\"upload2\")\nexcept TypeError as e:\n    if \"both a name\" in str(e):\n        deco = app.tool(\"upload\")","preventionTips":["Pick one naming style (positional or keyword) and use it consistently","Search codebase for `tool(\"...\", name=` and `ui(\"...\", name=` patterns before refactors","Let the function __name__ be the default when no custom name is needed"],"tags":["python","typeerror","decorator-usage"],"backgroundTag":"duplicate-argument-specified","analyzedSha":"1f021142978e0861cd910c8df4e8074bc7cf3978","analyzedAt":"2026-08-29T14:31:16.082Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}