microsoft/qlib · critical · ValueError

Invalid Qlib configuration (note: the global config has alre

Error message

Invalid Qlib configuration (note: the global config has already been updated):
Invalid Qlib configuration:
- {errors}

What it means

qlib's global config (qlib/config.py) now validates itself after qlib.init() updates it: provider_uri must be set and region must be specified ('cn' or 'us'). If either is missing the ValueError lists all problems, and importantly the global config has ALREADY been mutated before validation fails — a subsequent init in the same process operates on partially-updated state.

Source

Thrown at qlib/config.py:82

class Config:
    def __init__(self, default_conf):
        self.__dict__["_default_config"] = copy.deepcopy(default_conf)
        self.reset()

    # TODO: This validation logic is a temporary solution.
    # The long-term goal is to migrate Qlib Config to a typed configuration
    # system based on pydantic.BaseModel, with explicit schema and field validation.
    def validate(self):
        errors = []

        if not self.get("provider_uri"):
            errors.append("provider_uri must be set (e.g. ~/.qlib/qlib_data or a valid path)")

        if not self.get("region"):
            errors.append("region must be specified (e.g. 'cn', 'us')")

        if errors:
            raise ValueError(
                "Invalid Qlib configuration (note: the global config has already been updated):\n"
                "Invalid Qlib configuration:\n- " + "\n- ".join(errors)
            )

    def __getitem__(self, key):
        return self.__dict__["_config"][key]

    def __getattr__(self, attr):
        if attr in self.__dict__["_config"]:
            return self.__dict__["_config"][attr]
        raise AttributeError(f"No such `{attr}` in self._config")

    def get(self, key, default=None):
        return self.__dict__["_config"].get(key, default)

    def __setitem__(self, key, value):
        self.__dict__["_config"][key] = value

View on GitHub (pinned to 79633dd950)

Solutions

  1. Always pass both keys to qlib.init: qlib.init(provider_uri='~/.qlib/qlib_data/cn_data', region='cn').
  2. If provider data is not ready, point provider_uri at the intended location anyway (existence is checked later by data loading, not by init).
  3. After this error in a long-lived process, restart the process or fully reset the global config before re-initializing, since the global config was already partially updated.
  4. Use qlib.init_from_yaml or checked example configs from the qlib repo as a template.

Example fix

# before
qlib.init(region='cn')  # provider_uri missing -> ValueError
# after
qlib.init(provider_uri='~/.qlib/qlib_data/cn_data', region='cn')
Defensive patterns

Strategy: validation

Validate before calling

import qlib.config as cfg
missing = [k for k in ('provider_uri', 'region') if not cfg.get(k)]
if missing:
    raise ValueError(f'qlib config missing required keys: {missing}')

Try / catch

try:
    qlib.init(**init_kwargs)
except ValueError as e:
    if 'Invalid Qlib configuration' in str(e):
        init_kwargs.setdefault('provider_uri', '~/.qlib/qlib_data/cn_data')
        init_kwargs.setdefault('region', 'cn')
        qlib.init(**init_kwargs)
    else:
        raise

Prevention

When it happens

Trigger: Calling qlib.init() without a provider_uri (e.g. only passing region), or constructing QlibConfig and calling validate() before region/provider_uri defaults are filled; also triggered by config updates that delete or blank these keys.

Common situations: Fresh setups that skip provider_uri because they intend to set a custom data provider later; programmatic init with an empty dict; version migration where older qlib silently defaulted provider_uri but the new typed-config validation rejects it.

Related errors


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