PrefectHQ/fastmcp · error · ImportError
Failed to reload module {file_path}: {e}
Error message
Failed to reload module {file_path}: {e} What it means
When the module was already imported (hot-reload path), FastMCP re-execs it in place by resetting `__spec__`/`__loader__`/`__file__` and calling `spec.loader.exec_module`. Any exception during that re-execution — not just ImportError — is wrapped in this ImportError with the file path.
Source
Thrown at fastmcp_slim/fastmcp/server/providers/filesystem_discovery.py:263
sys.path.insert(0, parent_dir)
try:
spec = importlib.util.spec_from_file_location(module_name, file_path)
if spec is None or spec.loader is None:
raise ImportError(f"Cannot load spec for {file_path}")
existing = sys.modules.get(module_name)
if existing is not None:
# Re-exec in place rather than importlib.reload: reload() re-finds
# the module by name via sys.path, which fails for private keys
# (the file is tool.py, not _fastmcp_tool_xxx.py).
existing.__spec__ = spec
existing.__loader__ = spec.loader
existing.__file__ = str(file_path)
try:
spec.loader.exec_module(existing)
except Exception as e:
raise ImportError(
f"Failed to reload module {file_path}: {e}"
) from e
return existing
module = importlib.util.module_from_spec(spec)
sys.modules[module_name] = module
try:
spec.loader.exec_module(module)
except Exception as e:
# Clean up sys.modules on failure
sys.modules.pop(module_name, None)
raise ImportError(f"Failed to execute module {file_path}: {e}") from e
return module
finally:
if path_added:
with contextlib.suppress(ValueError):View on GitHub (pinned to 1f02114297)
Solutions
- Fix the error in the source file — the chained cause shows the original exception and line
- Validate the file compiles before saving: `python -m py_compile plugin.py`
- Avoid module-level side effects; move connection/startup logic into functions
- Re-trigger discovery once the file is fixed so the module re-executes cleanly
Example fix
// before # plugin.py (edited) def tool(): ... run_setup() # NameError: run_setup was deleted // after # plugin.py def tool(): ... # remove the call or re-import run_setup
Defensive patterns
Strategy: try-catch
Validate before calling
import py_compile
py_compile.compile('plugin.py', doraise=True) # raises on syntax errors before reload Try / catch
try:
mod = provider.import_module_from_file(path) # reload path
except ImportError as e:
log.error('reload of %s failed: %s', path, e.__cause__)
# keep serving the previous module version; fix source before retrying Prevention
- Keep module-level code free of side effects and failures
- Compile-check files before saving to the watched directory
- Avoid deleting/moving helper modules that loaded files import
When it happens
Trigger: Reload of an existing module whose new source raises at import time: NameError, SyntaxError, missing dependency, or module-level code that fails (e.g. connecting to a service).
Common situations: Editing a tool file and introducing a typo or undefined name; reloading after renaming an imported helper; module-level side effects (DB connections) failing on reload.
Related errors
- Failed to import {module_name} from {file_path}: {e}
- Failed to execute module {file_path}: {e}
- module {__name__!r} has no attribute {name!r}
- Cannot resolve tool reference: {fn!r}
- Cannot specify both a name as first argument and as keyword
AI-assisted analysis of PrefectHQ/fastmcp@1f02114297 (2026-08-29).
Data as JSON: /api/errors/077560a26c2e9300.
Report an issue: GitHub.