microsoft/qlib · error · ModuleNotFoundError

None is passed in as parameters as module_path

Error message

None is passed in as parameters as module_path

What it means

qlib.utils.mod.get_module_by_module_path loads a module from a filesystem path (.py), a dotted module path, or a ModuleType. Passing None is treated as a programming/configuration mistake and raises ModuleNotFoundError immediately rather than failing obscurely inside importlib. Note: this is raised via raise, so it propagates even though ModuleNotFoundError normally signals a missing package.

Source

Thrown at qlib/utils/mod.py:33

import re
import sys
from types import ModuleType
from typing import Any, Dict, List, Tuple, Union
from urllib.parse import urlparse

from qlib.typehint import InstConf
from qlib.utils.pickle_utils import restricted_pickle_load


def get_module_by_module_path(module_path: Union[str, ModuleType]):
    """Load module path

    :param module_path:
    :return:
    :raises: ModuleNotFoundError
    """
    if module_path is None:
        raise ModuleNotFoundError("None is passed in as parameters as module_path")

    if isinstance(module_path, ModuleType):
        module = module_path
    else:
        if module_path.endswith(".py"):
            module_name = re.sub("^[^a-zA-Z_]+", "", re.sub("[^0-9a-zA-Z_]", "", module_path[:-3].replace("/", "_")))
            module_spec = importlib.util.spec_from_file_location(module_name, module_path)
            module = importlib.util.module_from_spec(module_spec)
            sys.modules[module_name] = module
            module_spec.loader.exec_module(module)
        else:
            module = importlib.import_module(module_path)
    return module


def split_module_path(module_path: str) -> Tuple[str, str]:
    """

View on GitHub (pinned to 79633dd950)

Solutions

  1. Remove the module_path key entirely (qlib then falls back to default_module) or set it to a real dotted path / .py file path.
  2. In config-building code, use config.pop('module_path', None) only when the value is truthy, or filter out None values before calling init_instance_by_config.
  3. If a string class name is used, put the full path 'a.b.c.ClassName' in the config string so split_module_path handles it.

Example fix

// before
conf = {'class': 'TopkDropoutStrategy', 'module_path': None}
inst = init_instance_by_config(conf)

// after
conf = {'class': 'TopkDropoutStrategy', 'module_path': 'qlib.contrib.strategy'}
inst = init_instance_by_config(conf)
Defensive patterns

Strategy: validation

Validate before calling

conf = {k: v for k, v in conf.items() if v is not None}  # drop null module_path
inst = init_instance_by_config(conf)

Type guard

def is_valid_module_path(mp) -> bool:
    return mp is None is False and (isinstance(mp, str) and len(mp) > 0)

Try / catch

try:
    inst = init_instance_by_config(conf)
except ModuleNotFoundError as e:
    if 'None is passed' in str(e):
        conf.pop('module_path', None)
        inst = init_instance_by_config(conf)
    else:
        raise

Prevention

When it happens

Trigger: init_instance_by_config({'class': 'MyHandler', 'module_path': None}) or get_callable_kwargs where a config dict's 'module_path' key exists but its value is None; dynamically built configs where a template left module_path unset.

Common situations: YAML/JSON workflow configs (e.g. qlib task or workflow configs) with an explicit `module_path: null`; code that reads module_path with config.get('module_path') instead of omitting the key; conditional config assembly that assigns None on a missing branch.

Related errors


AI-assisted analysis of microsoft/qlib@79633dd950 (2026-08-15). Data as JSON: /api/errors/4cde1a4f05bac522. Report an issue: GitHub.