PrefectHQ/fastmcp · error · ImportError

Failed to import {module_name} from {file_path}: {e}

Error message

Failed to import {module_name} from {file_path}: {e}

What it means

`import_module_from_file` imports a file as a submodule under a private package anchor (e.g. `_fastmcp_tool_xxx`). When `importlib.import_module(private_name)` raises ImportError — typically because a module imported *by* the target file cannot be resolved, or a relative import fails outside a proper package — it is re-raised with this message wrapping the original cause.

Source

Thrown at fastmcp_slim/fastmcp/server/providers/filesystem_discovery.py:199

        # normally beneath it.
        top_name = module_name.split(".")[0]
        existing_top = sys.modules.get(top_name)
        if existing_top is not None and not _package_path_matches(
            existing_top, package_root
        ):
            anchor = _private_package_prefix(package_root.parent)
            if anchor not in sys.modules:
                spec = ModuleSpec(anchor, loader=None, is_package=True)
                anchor_module = importlib.util.module_from_spec(spec)
                anchor_module.__path__ = [str(package_root.parent)]
                sys.modules[anchor] = anchor_module
            private_name = f"{anchor}.{module_name}"
            try:
                if private_name in sys.modules:
                    return importlib.reload(sys.modules[private_name])
                return importlib.import_module(private_name)
            except ImportError as e:
                raise ImportError(
                    f"Failed to import {module_name} from {file_path}: {e}"
                ) from e

        # Temporarily add package root's parent to sys.path for the import
        package_parent = str(package_root.parent)
        path_added = package_parent not in sys.path
        if path_added:
            sys.path.insert(0, package_parent)

        try:
            # If already imported, reload to pick up changes (for reload mode)
            if module_name in sys.modules:
                return importlib.reload(sys.modules[module_name])
            return importlib.import_module(module_name)
        except ImportError as e:
            raise ImportError(
                f"Failed to import {module_name} from {file_path}: {e}"
            ) from e

View on GitHub (pinned to 1f02114297)

Solutions

  1. Read the chained `__cause__` (`raise ... from e`) to see which inner import failed and install/fix that dependency
  2. Move relative imports (`from . import x`) to absolute imports or ensure the file lives in a real package with `__init__.py`
  3. Verify sys.path contains the directory the plugin file expects (the loader temporarily adds the package parent, but transitive deps may live elsewhere)
  4. Test the file standalone with `python -c "import your_module"` to reproduce the import error outside FastMCP

Example fix

// before
# plugin.py
from .helpers import build  # fails: not in a real package
// after
# plugin.py
from helpers import build  # absolute import, helpers.py next to plugin.py
Defensive patterns

Strategy: try-catch

Validate before calling

import ast, pathlib
def check_imports(path):
    tree = ast.parse(pathlib.Path(path).read_text())
    return [n for n in ast.walk(tree) if isinstance(n, ast.ImportFrom) and n.level > 0]

Type guard

def is_importable_py_file(p):
    return p.is_file() and p.suffix == '.py'

Try / catch

try:
    mod = provider.import_module_from_file(path)
except ImportError as e:
    log.error('import failed for %s: cause=%r', path, e.__cause__)

Prevention

When it happens

Trigger: Calling `discover_and_import` (or the tests) on a file whose module body does `import some_missing_lib` or uses `from . import x` when the file is not importable as a package; the private anchor package exists but the nested import fails.

Common situations: Discovered tool files with undeclared dependencies; files relying on relative imports but loaded outside a real package layout; PYTHONPATH missing a dependency; typos in imports inside hot-reloaded plugin files.

Related errors


AI-assisted analysis of PrefectHQ/fastmcp@1f02114297 (2026-08-29). Data as JSON: /api/errors/77ddf29dac97680b. Report an issue: GitHub.