{"record":{"id":"d3f5e32271747a3c","repo":"abhigyanpatwari/GitNexus","slug":"sandbox-copy-directory-is-unreadable-relative","errorCode":null,"errorMessage":"sandbox_copy directory is unreadable: {relative}: {exc}","messagePattern":"sandbox_copy directory is unreadable: (.+?): (.+?)","errorType":"exception","errorClass":"SandboxError","httpStatus":null,"severity":"error","filePath":"eval/workflow_bench/task_assets.py","lineNumber":394,"sourceCode":"        budget: _SnapshotBudget | None = None,\n        allow_symlinks: bool = False,\n        preserve_modes: bool = False,\n    ):\n        self.destination = destination\n        self.entries: dict[PurePosixPath, AssetManifestEntry] = {}\n        self.total_bytes = 0\n        self.budget = budget if budget is not None else _SnapshotBudget()\n        self.allow_symlinks = allow_symlinks\n        self.preserve_modes = preserve_modes\n\n    def copy_descriptor(self, descriptor: int, relative: PurePosixPath) -> None:\n        before = os.fstat(descriptor)\n        if stat.S_ISDIR(before.st_mode):\n            self._record_directory(relative)\n            try:\n                names = sorted(os.listdir(descriptor))\n            except OSError as exc:\n                raise SandboxError(f\"sandbox_copy directory is unreadable: {relative}: {exc}\") from exc\n            for name in names:\n                child_relative = relative / name\n                child_metadata = os.stat(name, dir_fd=descriptor, follow_symlinks=False)\n                if stat.S_ISLNK(child_metadata.st_mode):\n                    if not self.allow_symlinks:\n                        raise SandboxError(f\"sandbox_copy must not traverse a symlink: {child_relative}\")\n                    self._copy_symlink(descriptor, name, child_relative, child_metadata)\n                    continue\n                child = _open_child(descriptor, name, child_relative)\n                try:\n                    self.copy_descriptor(child, child_relative)\n                finally:\n                    os.close(child)\n            after = os.fstat(descriptor)\n            if _mutation_identity(before) != _mutation_identity(after):\n                raise SandboxError(f\"sandbox_copy directory changed while snapshotting: {relative}\")\n            return\n        if not stat.S_ISREG(before.st_mode):","sourceCodeStart":376,"sourceCodeEnd":412,"githubUrl":"https://github.com/abhigyanpatwari/GitNexus/blob/d540b00184d71a896261ee02670da9a92d59d8f7/eval/workflow_bench/task_assets.py#L376-L412","documentation":"While snapshotting, os.listdir(descriptor) on a directory raised OSError, wrapped as a SandboxError with {relative} and {exc}. The snapshotter cannot enumerate the directory, so capture cannot be proven complete.","triggerScenarios":"A sandbox_copy source directory lacks read/execute permission for the runner, or hits an IO error (EIO) or vanishes (ENOENT) during TaskAssetCache.prepare.","commonSituations":"Permission bits on a vendored/generated directory; a mount returning EIO; a directory removed mid-snapshot by a concurrent writer.","solutions":["Inspect the chained OSError.errno (EACCES/EIO/ENOENT).","Fix permissions on the source tree (read+execute on directories, read on files).","Run on a reliable filesystem and ensure no concurrent deletion during capture.","Re-run prepare once the tree is stable."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"import os\n\ndef assert_source_listable(repo, relative):\n    p = os.path.join(repo, *relative.parts)\n    try:\n        with os.scandir(p) as it:\n            list(it)\n    except OSError as exc:\n        raise RuntimeError(f\"sandbox_copy dir unreadable: {relative}: {exc}\") from exc","typeGuard":null,"tryCatchPattern":"from workflow_bench.proposer_sandbox import SandboxError\n\ntry:\n    snapshot = cache.prepare(task, repo=repo, resolved_sha=sha)\nexcept SandboxError as exc:\n    if \"directory is unreadable\" in str(exc):\n        log.error(\"sandbox_copy permission/IO error - check dir r-x bits and filesystem health\")\n    raise","preventionTips":["Ensure read+execute bits on every sandbox_copy source directory for the runner UID.","Run on a reliable local filesystem, not a flaky mount.","Prevent concurrent deletion during snapshot capture."],"tags":["filesystem","workflow-bench","sandbox","permissions"],"backgroundTag":null,"analyzedSha":"d540b00184d71a896261ee02670da9a92d59d8f7","analyzedAt":"2026-08-12T19:50:25.132Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}