facebookresearch/detectron2 · error · ImportError

Cannot import from {cur_file_no_suffix}.

Error message

Cannot import from {cur_file_no_suffix}.

What it means

The patched relative import in config files found a directory where a .py config file was expected: it built cur_file, appended .py, saw the file didn't exist, but a matching directory (cur_file minus .py) does exist. Relative imports inside configs may only target config files, not packages/directories.

Source

Thrown at detectron2/config/lazy.py:138

Within a config file, relative import can only import other config files.
""".replace(
            "\n", " "
        )
        if not len(relative_import_path):
            raise ImportError(relative_import_err)

        cur_file = os.path.dirname(original_file)
        for _ in range(level - 1):
            cur_file = os.path.dirname(cur_file)
        cur_name = relative_import_path.lstrip(".")
        for part in cur_name.split("."):
            cur_file = os.path.join(cur_file, part)
        if not cur_file.endswith(".py"):
            cur_file += ".py"
        if not PathManager.isfile(cur_file):
            cur_file_no_suffix = cur_file[: -len(".py")]
            if PathManager.isdir(cur_file_no_suffix):
                raise ImportError(f"Cannot import from {cur_file_no_suffix}." + relative_import_err)
            else:
                raise ImportError(
                    f"Cannot import name {relative_import_path} from "
                    f"{original_file}: {cur_file} does not exist."
                )
        return cur_file

    def new_import(name, globals=None, locals=None, fromlist=(), level=0):
        if (
            # Only deal with relative imports inside config files
            level != 0
            and globals is not None
            and (globals.get("__package__", "") or "").startswith(_CFG_PACKAGE_NAME)
        ):
            cur_file = find_relative_file(globals["__file__"], name, level)
            _validate_py_syntax(cur_file)
            spec = importlib.machinery.ModuleSpec(
                _random_package_name(cur_file), None, origin=cur_file

View on GitHub (pinned to a2f4a8771a)

Solutions

  1. Rename the target so it is a config file: use from .models_config import X with models_config.py present
  2. If you want to import real code, use the absolute package path (from myproj.models import X), which the patched import forwards to the real __import__
  3. Flatten config directory structure to plain .py files

Example fix

# before
from .models import model  # models/ is a directory
# after
from mypkg.configs.models import model  # absolute import of real module
# or create models.py config file
Defensive patterns

Strategy: validation

Validate before calling

import os, re
for m in re.finditer(r"^\s*from\s+(\.+)([\w.]*)\s+import", open(cfg_path).read(), re.M):
    target = os.path.join(os.path.dirname(cfg_path), *m.group(2).split('.')) + '.py'
    assert os.path.isfile(target), f"{target} is not a config file (dir?)"

Try / catch

try:
    cfg = LazyConfig.load(path)
except ImportError as e:
    if "Cannot import from" in str(e):
        print("use absolute import for packages; relative only for .py configs")
    raise

Prevention

When it happens

Trigger: In a config .py: 'from .models import something' where models/ is a directory (Python package) rather than models.py, under the patched import used by LazyConfig.load.

Common situations: Structuring configs like a package with subfolders and using relative imports; mixing regular Python modules into config directories.

Related errors


AI-assisted analysis of facebookresearch/detectron2@a2f4a8771a (2026-08-27). Data as JSON: /api/errors/746626834a615663. Report an issue: GitHub.