diff --git a/backend/packages/harness/deerflow/community/aio_sandbox/quarantine.py b/backend/packages/harness/deerflow/community/aio_sandbox/quarantine.py index 202c7a5c8f..9908bce300 100644 --- a/backend/packages/harness/deerflow/community/aio_sandbox/quarantine.py +++ b/backend/packages/harness/deerflow/community/aio_sandbox/quarantine.py @@ -21,7 +21,13 @@ class SandboxQuarantine: @staticmethod def _key(value: str) -> str: - return hashlib.sha256(value.encode("utf-8")).hexdigest() + # Truncate to 16 hex chars (64 bits). The quarantine nests three hashed + # components (scope, sandbox id, container id); three full 64-char + # SHA-256 hexdigests exceed Windows' 260-char MAX_PATH when the root + # lives under a long path, failing record creation with ENOENT. 64 bits + # is far beyond what non-adversarial sandbox/container ids need, and + # matches the sandbox-naming convention elsewhere in this module. + return hashlib.sha256(value.encode("utf-8")).hexdigest()[:16] def _directory(self, info: SandboxInfo) -> Path: return self._root / self._key(info.sandbox_id) diff --git a/backend/tests/test_sandbox_quarantine.py b/backend/tests/test_sandbox_quarantine.py index dfe9f087c5..eda32e1e21 100644 --- a/backend/tests/test_sandbox_quarantine.py +++ b/backend/tests/test_sandbox_quarantine.py @@ -90,3 +90,14 @@ def test_retire_replaced_generations_keeps_unversioned_crash_fence(tmp_path): store.retire_replaced_generations(SandboxInfo("thread-sandbox", "http://sandbox", container_id="new-generation")) assert (directory / "unknown").exists() + + +def test_quarantine_keys_are_truncated_for_windows_max_path(): + # The quarantine nests three hashed path components (scope, sandbox id, + # container id). Three full 64-char SHA-256 hexdigests exceed Windows' + # 260-char MAX_PATH under a long root, so each key is truncated to 16 hex + # chars (64 bits). Pin that bound so a revert can't silently re-break + # Windows record creation while Linux CI still passes. + assert len(SandboxQuarantine._key("thread-sandbox")) == 16 + assert len(SandboxQuarantine._key("provisioner-a")) == 16 + assert len(SandboxQuarantine._key("old-generation")) == 16