microsoft/qlib · error · IOError

Only py/yml/yaml/json type are supported now!

Error message

Only py/yml/yaml/json type are supported now!

What it means

parse_backtest_config (qlib/rl/contrib/naive_config_parser.py:37) dispatches on the file extension and only supports .py, .json, .yaml, and .yml backtest configs (py configs are imported as a temp module; json/yaml are parsed). Any other extension (.yml.bak, .toml, .ini, .txt, no extension) raises IOError("Only py/yml/yaml/json type are supported now!").

Source

Thrown at qlib/rl/contrib/naive_config_parser.py:37

            v.pop(DELETE_KEY, False)
            b[k] = merge_a_into_b(v, b[k])
        else:
            b[k] = v
    return b


def check_file_exist(filename: str, msg_tmpl: str = 'file "{}" does not exist') -> None:
    if not os.path.isfile(filename):
        raise FileNotFoundError(msg_tmpl.format(filename))


def parse_backtest_config(path: str) -> dict:
    abs_path = os.path.abspath(path)
    check_file_exist(abs_path)

    file_ext_name = os.path.splitext(abs_path)[1]
    if file_ext_name not in (".py", ".json", ".yaml", ".yml"):
        raise IOError("Only py/yml/yaml/json type are supported now!")

    with tempfile.TemporaryDirectory() as tmp_config_dir:
        with tempfile.NamedTemporaryFile(dir=tmp_config_dir, suffix=file_ext_name) as tmp_config_file:
            if platform.system() == "Windows":
                tmp_config_file.close()

            tmp_config_name = os.path.basename(tmp_config_file.name)
            shutil.copyfile(abs_path, tmp_config_file.name)

            if abs_path.endswith(".py"):
                tmp_module_name = os.path.splitext(tmp_config_name)[0]
                sys.path.insert(0, tmp_config_dir)
                module = import_module(tmp_module_name)
                sys.path.pop(0)

                config = {k: v for k, v in module.__dict__.items() if not k.startswith("__")}

                del sys.modules[tmp_module_name]

View on GitHub (pinned to 79633dd950)

Solutions

  1. Rename the config to end in .py, .json, .yaml, or .yml
  2. Convert TOML/INI configs to YAML before passing them to parse_backtest_config
  3. Filter globbed file lists by allowed suffixes before parsing

Example fix

# before
config = parse_backtest_config('backtest_config.toml')  # IOError

# after
# convert to yaml, then
config = parse_backtest_config('backtest_config.yaml')
Defensive patterns

Strategy: validation

Validate before calling

from pathlib import Path
ext = Path(path).suffix.lower()
assert ext in ('.py', '.json', '.yaml', '.yml'), f'unsupported config extension: {ext}'

Type guard

def is_supported_config(path) -> bool:
    return Path(path).suffix.lower() in ('.py', '.json', '.yaml', '.yml')

Try / catch

try:
    cfg = parse_backtest_config(path)
except IOError as e:
    raise ValueError('convert config to .py/.json/.yaml/.yml') from e

Prevention

When it happens

Trigger: Calling parse_backtest_config on files with extensions outside (.py, .json, .yaml, .yml), e.g. 'config.toml', 'config.yml.bak', 'config.txt', or extensionless files.

Common situations: Renaming configs (leaving .bak or ~ suffixes); trying to use TOML/INI configs with the RL backtest entry point; editor temp files being picked up by glob patterns.

Related errors


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