{"record":{"id":"91c03e2226b7a4e1","repo":"PrefectHQ/fastmcp","slug":"version-must-be-a-string-int-or-float-got-bool","errorCode":null,"errorMessage":"Version must be a string, int, or float, got bool: {v!r}","messagePattern":"Version must be a string, int, or float, got bool: (.+?)","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"fastmcp_slim/fastmcp/utilities/components.py","lineNumber":57,"sourceCode":"def _convert_set_default_none(maybe_set: set[T] | Sequence[T] | None) -> set[T]:\n    \"\"\"Convert a sequence to a set, defaulting to an empty set if None.\"\"\"\n    if maybe_set is None:\n        return set()\n    if isinstance(maybe_set, set):\n        return maybe_set\n    return set(maybe_set)\n\n\ndef _coerce_version(v: str | int | float | None) -> str | None:\n    \"\"\"Coerce version to string, accepting int, float, or str.\n\n    Raises TypeError for non-scalar types (list, dict, set, etc.).\n    Raises ValueError if version contains '@' (used as key delimiter).\n    \"\"\"\n    if v is None:\n        return None\n    if isinstance(v, bool):\n        raise TypeError(f\"Version must be a string, int, or float, got bool: {v!r}\")\n    if not isinstance(v, (str, int, float)):\n        raise TypeError(\n            f\"Version must be a string, int, or float, got {type(v).__name__}: {v!r}\"\n        )\n    version = str(v)\n    if \"@\" in version:\n        raise ValueError(\n            f\"Version string cannot contain '@' (used as key delimiter): {version!r}\"\n        )\n    return version\n\n\nclass FastMCPComponent(FastMCPBaseModel):\n    \"\"\"Base class for FastMCP tools, prompts, resources, and resource templates.\"\"\"\n\n    KEY_PREFIX: ClassVar[str] = \"\"\n\n    def __init_subclass__(cls, **kwargs: Any) -> None:","sourceCodeStart":39,"sourceCodeEnd":75,"githubUrl":"https://github.com/PrefectHQ/fastmcp/blob/1f021142978e0861cd910c8df4e8074bc7cf3978/fastmcp_slim/fastmcp/utilities/components.py#L39-L75","documentation":"FastMCP component versions must be scalar (str, int, or float). Booleans are explicitly rejected even though bool is a subclass of int in Python, because version=True is surely unintended and would otherwise coerce to \"True\". A TypeError is raised naming the offending value.","triggerScenarios":"Passing version=True/False to a component constructor (tool, resource, prompt, etc.) or to from_tool/versioned registration, often from unvalidated config or dynamic values.","commonSituations":"YAML/JSON config where a version is written as `true`; a flag variable accidentally passed as the version argument; dynamic version variables that can hold booleans.","solutions":["Pass a real string/int/float version, e.g. version=\"1.0.0\"","Fix the config so the version field is quoted as a string","Validate/coerce the version value before constructing the component"],"exampleFix":"// before\nTool(fn, name=\"t\", version=True)\n\n// after\nTool(fn, name=\"t\", version=\"1.0.0\")","handlingStrategy":"type-guard","validationCode":"def valid_version(v) -> bool:\n    return v is None or (isinstance(v, (str, int, float)) and not isinstance(v, bool))","typeGuard":"def is_scalar_version(v: object) -> bool:\n    return isinstance(v, (str, int, float)) and not isinstance(v, bool)","tryCatchPattern":"try:\n    tool = Tool(fn, version=v)\nexcept TypeError as e:\n    if \"got bool\" in str(e):\n        tool = Tool(fn, version=str(int(v)))\n    else:\n        raise","preventionTips":["Quote version strings in YAML/JSON configs","Never pass boolean flags in the version parameter position","Validate config values before constructing components"],"tags":["python","typeerror","versioning","components"],"backgroundTag":"invalid-version-type","analyzedSha":"1f021142978e0861cd910c8df4e8074bc7cf3978","analyzedAt":"2026-08-29T14:31:16.082Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}