{"record":{"id":"e07f12febb46f333","repo":"microsoft/qlib","slug":"failed-to-create-directory-mount-path-please-cr","errorCode":null,"errorMessage":"Failed to create directory {mount_path}, please create {mount_path} manually!","messagePattern":"Failed to create directory (.+?), please create (.+?) manually!","errorType":"exception","errorClass":"OSError","httpStatus":null,"severity":"error","filePath":"qlib/__init__.py","lineNumber":164,"sourceCode":"                        if isinstance(_c, str):\n                            _temp_mount = _c.split(\" \")[2]\n                        else:\n                            _temp_mount = _c.decode(\"utf-8\").split(\" \")[2]\n                        _temp_mount = _temp_mount[:-1] if _temp_mount.endswith(\"/\") else _temp_mount\n                        if _temp_mount == _mount_path:\n                            _is_mount = True\n                            break\n                if _is_mount:\n                    break\n                _remote_uri = \"/\".join(_remote_uri.split(\"/\")[:-1])\n                _mount_path = \"/\".join(_mount_path.split(\"/\")[:-1])\n                _check_level_num -= 1\n\n            if not _is_mount:\n                try:\n                    Path(mount_path).mkdir(parents=True, exist_ok=True)\n                except Exception as e:\n                    raise OSError(\n                        f\"Failed to create directory {mount_path}, please create {mount_path} manually!\"\n                    ) from e\n\n                # check nfs-common\n                command_res = os.popen(\"dpkg -l | grep nfs-common\")\n                command_res = command_res.readlines()\n                if not command_res:\n                    raise OSError(\"nfs-common is not found, please install it by execute: sudo apt install nfs-common\")\n                # manually mount\n                try:\n                    subprocess.run(mount_command, check=True, capture_output=True, text=True)\n                    LOG.info(\"Mount finished.\")\n                except subprocess.CalledProcessError as e:\n                    if e.returncode == 256:\n                        raise OSError(\"Mount failed: requires sudo or permission denied\") from e\n                    elif e.returncode == 32512:\n                        raise OSError(f\"mount {provider_uri} on {mount_path} error! Command error\") from e\n                    else:","sourceCodeStart":146,"sourceCodeEnd":182,"githubUrl":"https://github.com/microsoft/qlib/blob/79633dd9506ea689e5400dea0197717b5b3d74b7/qlib/__init__.py#L146-L182","documentation":"CacheUtils.acquire (qlib/data/cache.py:245) wraps redis-based writer locks. redis_lock.AlreadyAcquired means the redis key 'lock:<name>-wlock' is currently held (or was left over from a crashed process), so the new acquirer gets a QlibCacheException with step-by-step instructions. It is qlib's guard against concurrent cache writers, surfaced as a RuntimeError subclass (QlibCacheException).","triggerScenarios":"Two processes simultaneously generating the same expression/dataset cache with redis configured as the lock backend (C.redis_host set); or a previous run was killed while holding the redis lock and the key never expired, so every subsequent run fails to acquire it.","commonSituations":"Multi-process data preparation (dump_bin, cache warm-up) with the same redis DB; leftover locks after OOM-kill or Ctrl-C; redis configured with no TTL on lock keys; shared redis across users/environments so key names collide.","solutions":["Follow the message: connect with redis-cli, SELECT the db shown (C.redis_task_db), DEL the exact key 'lock:<name>-wlock' listed in the error, then rerun","If multiple stale keys exist, the message suggests KEYS * to enumerate and FLUSHALL (only on a redis dedicated to qlib locks!)","Ensure no other qlib process is legitimately still writing the same cache before deleting the lock","Consider configuring lock expiration/TTL or using a dedicated redis DB per environment to avoid collisions"],"exampleFix":"# as the error message instructs:\nredis-cli\n> select 1            # the db from C.redis_task_db\n> del \"lock:dataset-<hash>-wlock\"\n> quit\n# then rerun your qlib command","handlingStrategy":"retry","validationCode":"# check for a stale lock before starting a big cache job\nimport redis  # same config as C.redis_host/port/task_db\nr = redis.Redis(host=C.redis_host, port=C.redis_port, db=C.redis_task_db)\nstale = [k for k in r.keys(\"lock:*-wlock\")]\nif stale:\n    print(f\"stale qlib locks present: {stale}\")  # decide cleanup before running","typeGuard":null,"tryCatchPattern":"from qlib.data.cache import QlibCacheException\n\nfor attempt in range(3):\n    try:\n        run_cache_job()\n        break\n    except QlibCacheException as e:\n        if \"redis lock\" not in str(e) or attempt == 2:\n            raise\n        clear_stale_lock(e)  # parse key from message, DEL it, backoff, retry","preventionTips":["Use a dedicated redis DB for qlib locks; record C.redis_task_db in the runbook","Install signal/exit handlers that release redis locks, or set TTLs","Delete 'lock:*-wlock' keys as the first step of any recovery procedure"],"tags":["qlib","redis","distributed-lock","concurrency","cache"],"backgroundTag":null,"analyzedSha":"79633dd9506ea689e5400dea0197717b5b3d74b7","analyzedAt":"2026-08-15T07:01:27.511Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}