PrefectHQ/fastmcp · error · TypeError
Cannot specify both a name as first argument and as keyword
Error message
Cannot specify both a name as first argument and as keyword argument.
What it means
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.
Source
Thrown at fastmcp_slim/fastmcp/apps/app.py:126
raise ValueError(f"Cannot resolve tool reference: {fn!r}")
return _resolve_tool_ref
def _dispatch_decorator(
name_or_fn: str | AnyFunction | None,
name: str | None,
register: Callable[[Any, str | None], Any],
decorator_name: str,
) -> Any:
"""Shared dispatch logic for @app.tool() and @app.ui() calling patterns."""
if inspect.isroutine(name_or_fn):
return register(name_or_fn, name)
if isinstance(name_or_fn, str):
if name is not None:
raise TypeError(
"Cannot specify both a name as first argument and as keyword argument."
)
tool_name: str | None = name_or_fn
elif name_or_fn is None:
tool_name = name
else:
raise TypeError(
f"First argument to @{decorator_name} must be a function, string, or None, "
f"got {type(name_or_fn)}"
)
def decorator(fn: F) -> F:
return register(fn, tool_name)
return decorator
# ---------------------------------------------------------------------------View on GitHub (pinned to 1f02114297)
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.
Example fix
// before
@app.tool("upload_file", name="upload")
def upload_file(...): ...
// after
@app.tool("upload")
def upload_file(...): ... Defensive patterns
Strategy: validation
Validate before calling
def check_tool_decorator_args(name_or_fn, name):
if isinstance(name_or_fn, str) and name is not None:
raise TypeError("Provide the tool name either positionally or as name=, not both") Type guard
def has_conflicting_names(name_or_fn, name) -> bool:
return isinstance(name_or_fn, str) and name is not None Try / catch
try:
deco = app.tool("upload", name="upload2")
except TypeError as e:
if "both a name" in str(e):
deco = app.tool("upload") Prevention
- 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
When it happens
Trigger: Calling `@app.tool("my_name", name="other_name")` or the equivalent with app.ui — a positional string name plus a keyword name.
Common situations: 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.
Related errors
- First argument to @{decorator_name} must be a function, stri
- A completion handler returned a str; return a list of string
- Got unexpected keyword argument(s): {', '.join(sorted(unknow
- Version must be a string, int, or float, got bool: {v!r}
- Version must be a string, int, or float, got {type(v).__name
AI-assisted analysis of PrefectHQ/fastmcp@1f02114297 (2026-08-29).
Data as JSON: /api/errors/e909c486560e6d0c.
Report an issue: GitHub.