microsoft/qlib · critical · OSError

nfs-common is not found, please install it by execute: sudo

Error message

nfs-common is not found, please install it by execute: sudo apt install nfs-common

What it means

Base ExpressionCache._uri (qlib/data/cache.py:353) is the abstract hook that maps (instrument, field, start_time, end_time, freq) to a cache-file URI for expression data. The base class has no mechanism of its own, so it raises NotImplementedError telling you to override it to match your cache mechanism. The public expression() method catches NotImplementedError from _expression and falls back to the wrapped provider, but _uri has no such fallback.

Source

Thrown at qlib/__init__.py:172

                if _is_mount:
                    break
                _remote_uri = "/".join(_remote_uri.split("/")[:-1])
                _mount_path = "/".join(_mount_path.split("/")[:-1])
                _check_level_num -= 1

            if not _is_mount:
                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

View on GitHub (pinned to 79633dd950)

Solutions

  1. If you just want disk caching, configure qlib.init(expression_cache=DiskExpressionCache) instead of a custom class
  2. In your subclass, override _uri to return the cache path/URI string for the given (instrument, field, start_time, end_time, freq)
  3. Follow the DiskExpressionCache implementation (cache.py) as the reference pattern

Example fix

# before
class MyExprCache(ExpressionCache):
    def _expression(self, instrument, field, start_time, end_time, freq):
        ...

# after
class MyExprCache(ExpressionCache):
    def _uri(self, instrument, field, start_time, end_time, freq):
        return str(self.cache_uri / f"{instrument}/{field}.bin")  # your mechanism
Defensive patterns

Strategy: type-guard

Validate before calling

from qlib.data.cache import ExpressionCache

assert MyExprCache._uri is not ExpressionCache._uri, \
    "custom ExpressionCache must override _uri"

Type guard

def is_usable_expr_cache(cls) -> bool:
    return all(
        getattr(cls, m) is not getattr(ExpressionCache, m)
        for m in ("_uri", "_expression", "update")
    )

Prevention

When it happens

Trigger: Instantiating a subclass of ExpressionCache that overrides _expression but not _uri (or using the base ExpressionCache directly) and calling a code path that needs the cache file location — e.g. uri(), update(), or client-side cache walking.

Common situations: Writing a custom expression cache (e.g. backed by S3, a DB) and missing one of the required overrides; note qlib ships DiskExpressionCache as the concrete implementation — use it unless you truly need a custom backend.

Related errors


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