PrefectHQ/fastmcp · error · ValueError
Cannot determine tool name for {fn!r}
Error message
Cannot determine tool name for {fn!r} What it means
When registering a tool, its name is taken from the explicit tool_name argument or the callable's __name__. If both are missing (the object has no __name__), _register cannot produce a unique tool name and raises this ValueError.
Source
Thrown at fastmcp_slim/fastmcp/apps/app.py:231
@app.tool
def save(name: str): ...
@app.tool()
def save(name: str): ...
@app.tool("custom_name")
def save(name: str): ...
"""
visibility: list[Literal["app", "model"]] = (
["app", "model"] if model else ["app"]
)
def _register(fn: F, tool_name: str | None) -> F:
from fastmcp.tools.base import Tool
resolved_name = tool_name or getattr(fn, "__name__", None)
if resolved_name is None:
raise ValueError(f"Cannot determine tool name for {fn!r}")
from fastmcp.apps.config import AppConfig, app_config_to_meta_dict
from fastmcp.server.providers.addressing import (
TOOL_HASH_META_KEY,
hash_tool,
)
app_config = AppConfig(visibility=visibility)
meta: dict[str, Any] = {
"ui": app_config_to_meta_dict(app_config),
"fastmcp": {
"app": self.name,
TOOL_HASH_META_KEY: hash_tool(self.name, resolved_name),
},
}
tool_obj = Tool.from_function(
fn,View on GitHub (pinned to 1f02114297)
Solutions
- Pass an explicit tool name: `@app.tool("my_tool_name")`.
- Restore __name__ on the callable (use functools.wraps in your decorator, or set `fn.__name__ = ...`).
- Register the underlying plain function instead of the wrapper object.
Example fix
// before
@app.tool()
def wrapper(): return partial_fn()
// after
@app.tool("my_tool")
def my_tool(): ...
# or: functools.wraps(original) inside the custom decorator Defensive patterns
Strategy: validation
Validate before calling
def ensure_nameable(fn, tool_name=None) -> None:
if tool_name is None and getattr(fn, "__name__", None) is None:
raise ValueError(f"Pass an explicit tool name for {fn!r}") Type guard
def has_derivable_name(fn) -> bool:
return getattr(fn, "__name__", None) is not None Try / catch
try:
app.tool()(fn)
except ValueError as e:
if "Cannot determine tool name" in str(e):
app.tool("explicit_name")(fn) Prevention
- Always apply functools.wraps in custom decorators
- Give callables a __name__ (even partials) before registering
- Pass an explicit name when registering wrapped/anonymous callables
When it happens
Trigger: Registering a callable lacking __name__ (e.g. functools.partial, a callable class instance, a custom decorator that did not use functools.wraps) without passing an explicit name.
Common situations: Decorating callables wrapped by third-party libraries; registering method-like objects; minified/proxied functions in tests (Mocks).
Related errors
- Cannot resolve tool reference: {fn!r}
- File {name!r} not found. Available: {available}
- File {f.get('name', '?')!r} exceeds max size ({_format_size(
- cache_ttl must be a positive integer, got {cache_ttl}
- ToolTransform has duplicate target name {target!r}: both {se
AI-assisted analysis of PrefectHQ/fastmcp@1f02114297 (2026-08-29).
Data as JSON: /api/errors/dd09d1be4131eb34.
Report an issue: GitHub.