PrefectHQ/fastmcp · error · TypeError
Version must be a string, int, or float, got {type(v).__name
Error message
Version must be a string, int, or float, got {type(v).__name__}: {v!r} What it means
Companion to the bool case: _coerce_version rejects any version value that is not str, int, or float (e.g. list, dict, None-adjacent objects) with a TypeError reporting the actual type. Versions are the component identity suffix (part of .key) so they must be scalar.
Source
Thrown at fastmcp_slim/fastmcp/utilities/components.py:59
if maybe_set is None:
return set()
if isinstance(maybe_set, set):
return maybe_set
return set(maybe_set)
def _coerce_version(v: str | int | float | None) -> str | None:
"""Coerce version to string, accepting int, float, or str.
Raises TypeError for non-scalar types (list, dict, set, etc.).
Raises ValueError if version contains '@' (used as key delimiter).
"""
if v is None:
return None
if isinstance(v, bool):
raise TypeError(f"Version must be a string, int, or float, got bool: {v!r}")
if not isinstance(v, (str, int, float)):
raise TypeError(
f"Version must be a string, int, or float, got {type(v).__name__}: {v!r}"
)
version = str(v)
if "@" in version:
raise ValueError(
f"Version string cannot contain '@' (used as key delimiter): {version!r}"
)
return version
class FastMCPComponent(FastMCPBaseModel):
"""Base class for FastMCP tools, prompts, resources, and resource templates."""
KEY_PREFIX: ClassVar[str] = ""
def __init_subclass__(cls, **kwargs: Any) -> None:
super().__init_subclass__(**kwargs)
# Warn if a subclass doesn't define KEY_PREFIX (inherited or its own)View on GitHub (pinned to 1f02114297)
Solutions
- Convert the version to a string/int/float before passing it, e.g. version=".".join(map(str, semver_list))
- Fix the config source so version is a scalar
- Use a simple string version like "1.2.0"
Example fix
// before version=[1, 2, 0] Tool(fn, version=version) // after version="1.2.0" Tool(fn, version=version)
Defensive patterns
Strategy: type-guard
Validate before calling
if not isinstance(v, (str, int, float)) or isinstance(v, bool):
v = str(v) # or normalize before passing Type guard
def is_scalar_version(v: object) -> bool:
return isinstance(v, (str, int, float)) and not isinstance(v, bool) Try / catch
try:
tool = Tool(fn, version=v)
except TypeError as e:
if "Version must be" in str(e):
tool = Tool(fn, version=str(v))
else:
raise Prevention
- Store versions as plain strings in configs
- Convert structured semver data to a string before use
- Add a schema check on version fields in config loaders
When it happens
Trigger: Passing a non-scalar like a list, dict, tuple, or datetime as the version argument to a FastMCP component or transform constructor.
Common situations: Passing a parsed semver list like [1, 2, 0] from config; passing a settings object attribute that is a dict; forgetting to stringify a custom version type.
Related errors
- Version must be a string, int, or float, got bool: {v!r}
- Cannot specify both a name as first argument and as keyword
- 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
AI-assisted analysis of PrefectHQ/fastmcp@1f02114297 (2026-08-29).
Data as JSON: /api/errors/d42136ca3049d7b5.
Report an issue: GitHub.