{"record":{"id":"53ec1cbaf9d82862","repo":"HKUDS/Vibe-Trading","slug":"run-dir-p-r-is-outside-allowed-run-roots-desc","errorCode":null,"errorMessage":"run_dir {p!r} is outside allowed run roots.\n{_describe_roots(roots)}\nSet {_ALLOWED_RUN_ROOTS_ENV} to add a run directory. {_ENV_SCOPE_HINT}","messagePattern":"run_dir (.+?) is outside allowed run roots\\.\n(.+?)\nSet (.+?) to add a run directory\\. (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"agent/src/tools/path_utils.py","lineNumber":365,"sourceCode":"    Args:\n        p: User/LLM-supplied run directory. `~` expansion is supported.\n\n    Returns:\n        Absolute resolved path inside an allowed run root.\n\n    Raises:\n        ValueError: If `p` is a UNC share or resolves outside all allowed run\n            roots.\n    \"\"\"\n    _rejects_unc(p)\n    resolved = Path(p).expanduser().resolve()\n\n    roots = _allowed_run_roots()\n    for root in roots:\n        if resolved.is_relative_to(root):\n            return resolved\n\n    raise ValueError(\n        f\"run_dir {p!r} is outside allowed run roots.\\n\"\n        f\"{_describe_roots(roots)}\\n\"\n        f\"Set {_ALLOWED_RUN_ROOTS_ENV} to add a run directory. {_ENV_SCOPE_HINT}\"\n    )\n\n\ndef safe_run_id(run_id: str) -> Path:\n    \"\"\"Resolve a bare run id to an existing allowed run directory.\n\n    Args:\n        run_id: Bare run directory name, not a path.\n\n    Returns:\n        Existing run directory under one of the allowed run roots.\n\n    Raises:\n        ValueError: If the run id is empty, path-shaped, or not found.\n    \"\"\"","sourceCodeStart":347,"sourceCodeEnd":383,"githubUrl":"https://github.com/HKUDS/Vibe-Trading/blob/80ffdda44c5c4db0dd84d70e051cca591cea67df/agent/src/tools/path_utils.py#L347-L383","documentation":"safe_run_dir resolves the supplied run_dir and requires it under one of _allowed_run_roots(); otherwise it raises with the allowed roots list and a hint to extend via the allowed-run-roots env var. Called by backtest/verification entry points before any run artifacts are touched.","triggerScenarios":"Passing run_dir=/some/random/dir when /some/random is not an allowed run root; common when pointing at a copied run directory outside the runs tree.","commonSituations":"Restored/archived runs moved off the standard runs directory, container volume mounts not in defaults, or env var set only in the dev shell.","solutions":["Keep run dirs under the configured runs directory","Add the parent directory via the allowed-run-roots env var (e.g. in the agent service unit)","Verify with the roots printed in the error message"],"exampleFix":"# before\nrun_dir=\"/mnt/restore/run-42\"\n# after\n# AGENT_ALLOWED_RUN_ROOTS=/mnt/restore\nrun_dir=\"/mnt/restore/run-42\"","handlingStrategy":"validation","validationCode":"cand = Path(run_dir).expanduser().resolve()\nassert any(cand.is_relative_to(r) for r in _allowed_run_roots()), \"run_dir outside allowed run roots\"","typeGuard":"def is_allowed_run_dir(rd: str) -> bool:\n    c = Path(rd).expanduser().resolve()\n    return any(c.is_relative_to(r) for r in _allowed_run_roots())","tryCatchPattern":"try:\n    rd = safe_run_dir(run_dir)\nexcept ValueError as e:\n    if \"outside allowed run roots\" in str(e):\n        os.environ[\"AGENT_ALLOWED_RUN_ROOTS\"] = str(Path(run_dir).parent); rd = safe_run_dir(run_dir)","preventionTips":["Never relocate run dirs off the runs tree","Set allowed-run-roots in the service environment","Copy restored runs back into the configured tree"],"tags":["run-dir","path-validation","environment-variable"],"backgroundTag":"missing-env-var","analyzedSha":"80ffdda44c5c4db0dd84d70e051cca591cea67df","analyzedAt":"2026-08-28T12:46:38.989Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}