facebookresearch/detectron2 · error · ValueError

Config file {filename} has to be a python or yaml file.

Error message

Config file {filename} has to be a python or yaml file.

What it means

LazyConfig.load only accepts files with a .py, .yaml, or .yml extension; the extension is checked with os.path.splitext before anything is read. Any other extension (or none) is rejected immediately.

Source

Thrown at detectron2/config/lazy.py:209

        assert caller_fname != "<string>", "load_rel Unable to find caller"
        caller_dir = os.path.dirname(caller_fname)
        filename = os.path.join(caller_dir, filename)
        return LazyConfig.load(filename, keys)

    @staticmethod
    def load(filename: str, keys: Union[None, str, Tuple[str, ...]] = None):
        """
        Load a config file.

        Args:
            filename: absolute path or relative path w.r.t. the current working directory
            keys: keys to load and return. If not given, return all keys
                (whose values are config objects) in a dict.
        """
        has_keys = keys is not None
        filename = filename.replace("/./", "/")  # redundant
        if os.path.splitext(filename)[1] not in [".py", ".yaml", ".yml"]:
            raise ValueError(f"Config file {filename} has to be a python or yaml file.")
        if filename.endswith(".py"):
            _validate_py_syntax(filename)

            with _patch_import():
                # Record the filename
                module_namespace = {
                    "__file__": filename,
                    "__package__": _random_package_name(filename),
                }
                with PathManager.open(filename) as f:
                    content = f.read()
                # Compile first with filename to:
                # 1. make filename appears in stacktrace
                # 2. make load_rel able to find its parent's (possibly remote) location
                exec(compile(content, filename, "exec"), module_namespace)

            ret = module_namespace
        else:

View on GitHub (pinned to a2f4a8771a)

Solutions

  1. Convert the file to .yaml/.yml or .py format and use that extension
  2. If it's JSON, rename/save as .yaml (JSON is valid YAML) and load again
  3. Filter file globs to *.py/*.yaml/*.yml before calling load

Example fix

# before
cfg = LazyConfig.load("configs/exp1.json")
# after
import json, yaml
data = json.load(open("configs/exp1.json"))
yaml.safe_dump(data, open("configs/exp1.yaml", "w"))
cfg = LazyConfig.load("configs/exp1.yaml")
Defensive patterns

Strategy: type-guard

Validate before calling

assert os.path.splitext(path)[1] in {'.py','.yaml','.yml'}, f"not a LazyConfig file: {path}"

Type guard

def is_lazyconfig_file(path: str) -> bool:
    return os.path.splitext(path)[1] in {".py", ".yaml", ".yml"}

Prevention

When it happens

Trigger: LazyConfig.load('config.json'), load('cfg.txt'), or a path whose extension is .pth/.pkl; also paths where '/./' normalization leaves a doubled extension.

Common situations: Feeding a YAML dump or JSON config from another tool into LazyConfig; scripts that glob config paths and accidentally pick up non-config files.

Related errors


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