PrefectHQ/fastmcp · error · KeyError
Tool version not found
Error message
Tool {name!r} version {version!r} not found What it means
When remove_tool is called with an explicit version, LocalProvider builds the versioned key f"{Tool.make_key(name)}@{version}" and raises KeyError if that exact key is absent. This means the tool name exists in concept but that specific version string does not match any registered version.
Solutions
- List the tool's registered versions (list all Tool components with that name) and remove an existing version string
- Omit the version argument to remove ALL versions of the tool
- Catch KeyError for idempotent teardown
- Ensure the version string used at removal exactly matches the one used at registration
Example fix
// before
provider.remove_tool("get_weather", "v1") # registered as "1.0.0" -> KeyError
// after
provider.remove_tool("get_weather", "1.0.0") # exact version match Defensive patterns
Strategy: validation
Validate before calling
versions = [c.version for c in provider._components.values()
if isinstance(c, Tool) and c.name == "my_tool"]
if "1.0.0" not in versions:
provider.remove_tool("my_tool") # remove all instead Type guard
def version_registered(provider, name: str, version: str) -> bool:
key = f"{Tool.make_key(name)}@{version}"
return key in provider._components Try / catch
try:
provider.remove_tool("my_tool", "1.0.0")
except KeyError:
provider.remove_tool("my_tool") # fall back to removing all versions Prevention
- Use one canonical version string constant for both add and remove
- Never pass a version unless you know the tool was registered versioned
- Prefer omitting version (removes all) in teardown code
When it happens
Trigger: provider.remove_tool("name", "1.0.0") where the tool was registered with version "1.0" (no patch), unversioned, or under a different version string entirely.
Common situations: Version-string mismatches between registration and removal (e.g. "v1" vs "1.0.0"); removing a version after an earlier teardown already deleted it; assuming a default version exists when the tool was added unversioned.
Related errors
- Prompt version not found
- Resource version not found
- Template version not found
- Tool not found
- Prompt not found
AI-assisted analysis of PrefectHQ/fastmcp@1f02114297 (2026-08-29).
Data as JSON: /api/errors/5b1311f1d1de76e5.
Report an issue: GitHub.
Appendix: source
Thrown at fastmcp_slim/fastmcp/server/providers/local_provider/local_provider.py:254
Raises:
KeyError: If no matching tool is found.
"""
if version is None:
# Remove all versions
keys_to_remove = [
k
for k, c in self._components.items()
if isinstance(c, Tool) and c.name == name
]
if not keys_to_remove:
raise KeyError(f"Tool {name!r} not found")
for key in keys_to_remove:
self._remove_component(key)
else:
# Remove specific version - key format is "tool:name@version"
key = f"{Tool.make_key(name)}@{version}"
if key not in self._components:
raise KeyError(f"Tool {name!r} version {version!r} not found")
self._remove_component(key)
def remove_resource(self, uri: str, version: str | None = None) -> None:
"""Remove resource(s) from this provider's storage.
Args:
uri: The resource URI.
version: If None, removes ALL versions. If specified, removes only that version.
Raises:
KeyError: If no matching resource is found.
"""
if version is None:
# Remove all versions
keys_to_remove = [
k
for k, c in self._components.items()
if isinstance(c, Resource) and str(c.uri) == uriView on GitHub (pinned to 1f02114297)