microsoft/qlib · critical · OSError

Mount failed: {e.stderr}

Error message

Mount failed: {e.stderr}

What it means

DatasetCache._uri (qlib/data/cache.py:423) is the abstract hook that maps (instruments, fields, start_time, end_time, freq) to a dataset cache file URI. The base DatasetCache provides no storage mechanism, so _uri raises NotImplementedError. Unlike _dataset, there is no automatic fallback for URI resolution — code paths like DatasetCache.dataset with disk_cache=1 or _dataset_uri call _uri directly.

Source

Thrown at qlib/__init__.py:183

                        f"Failed to create directory {mount_path}, please create {mount_path} manually!"
                    ) from e

                # check nfs-common
                command_res = os.popen("dpkg -l | grep nfs-common")
                command_res = command_res.readlines()
                if not command_res:
                    raise OSError("nfs-common is not found, please install it by execute: sudo apt install nfs-common")
                # manually mount
                try:
                    subprocess.run(mount_command, check=True, capture_output=True, text=True)
                    LOG.info("Mount finished.")
                except subprocess.CalledProcessError as e:
                    if e.returncode == 256:
                        raise OSError("Mount failed: requires sudo or permission denied") from e
                    elif e.returncode == 32512:
                        raise OSError(f"mount {provider_uri} on {mount_path} error! Command error") from e
                    else:
                        raise OSError(f"Mount failed: {e.stderr}") from e
            else:
                LOG.warning(f"{_remote_uri} on {_mount_path} is already mounted")


def init_from_yaml_conf(conf_path, **kwargs):
    """init_from_yaml_conf

    :param conf_path: A path to the qlib config in yml format
    """

    if conf_path is None:
        config = {}
    else:
        with open(conf_path) as f:
            yaml = YAML(typ="safe", pure=True)
            config = yaml.load(f)
    config.update(kwargs)
    default_conf = config.pop("default_conf", "client")

View on GitHub (pinned to 79633dd950)

Solutions

  1. Configure qlib.init(dataset_cache=DiskDatasetCache) for standard file-based dataset caching
  2. In a custom subclass, override _uri(self, instruments, fields, start_time, end_time, freq, **kwargs) to return the cache file path string
  3. Model the override on DiskDatasetCache._uri, which hashes the arguments to build the path

Example fix

# before
qlib.init(dataset_cache=MyPartialCache)  # _uri missing -> D.features(disk_cache=1) fails

# after
from qlib.data.cache import DiskDatasetCache
qlib.init(dataset_cache=DiskDatasetCache)
Defensive patterns

Strategy: type-guard

Validate before calling

from qlib.data.cache import DatasetCache

assert MyDSCache._uri is not DatasetCache._uri, \
    "custom DatasetCache must override _uri before enabling disk_cache=1"

Type guard

def is_usable_ds_cache(cls) -> bool:
    return all(
        getattr(cls, m) is not getattr(DatasetCache, m)
        for m in ("_uri", "_dataset", "_dataset_uri", "update")
    )

Prevention

When it happens

Trigger: Using a DatasetCache subclass that overrides _dataset but not _uri (or the base class itself) and calling D.features(..., disk_cache=1) / DatasetCache.dataset, which resolves the cache URI before reading; also hit by cache-maintenance code calling uri().

Common situations: Custom dataset cache backends with partial overrides; the concrete implementation users should reach for is DiskDatasetCache (or SimpleDatasetCache/DatasetURICache) in the same module.

Related errors


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