microsoft/qlib · warning · OSError

Mount failed: requires sudo or permission denied

Error message

Mount failed: requires sudo or permission denied

What it means

Base ExpressionCache._expression (qlib/data/cache.py:360) is the abstract method that actually reads expression data from the cache. The base raises NotImplementedError('Implement this method if you want to use expression cache'); the public expression() wrapper catches that NotImplementedError and transparently falls back to self.provider.expression(...), i.e. without a cache you silently pay the cost of loading from the underlying provider.

Source

Thrown at qlib/__init__.py:179

                try:
                    Path(mount_path).mkdir(parents=True, exist_ok=True)
                except Exception as e:
                    raise OSError(
                        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:

View on GitHub (pinned to 79633dd950)

Solutions

  1. Use the shipped qlib.data.cache.DiskExpressionCache if file-based caching is what you want
  2. Override _expression(self, instrument, field, start_time, end_time, freq) -> pd.Series in your subclass to read from your cache backend
  3. Pair it with _uri and update overrides — all three must be consistent

Example fix

# before
qlib.init(expression_cache=MyBrokenCache)  # _expression not overridden -> no caching

# after
from qlib.data.cache import DiskExpressionCache
qlib.init(expression_cache=DiskExpressionCache, expression_cache_disk_path=...)
Defensive patterns

Strategy: fallback

Validate before calling

from qlib.data.cache import ExpressionCache

if MyExprCache._expression is ExpressionCache._expression:
    print("WARNING: expression cache disabled (falls back to provider)")

Try / catch

# expression() already falls back to the provider on NotImplementedError;
# detect the silent no-cache path by timing or by checking cache dir growth

Prevention

When it happens

Trigger: Registering a custom ExpressionCache subclass without overriding _expression: data still loads (via provider fallback) but nothing is cached; calling _expression directly always raises; subclass forgot to also override _uri, in which case uri-related calls fail separately.

Common situations: Boilerplate custom cache classes where only the constructor was customized; misreading the API — assuming the base class provides a default file-based cache (it does not; that is DiskExpressionCache).

Related errors


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