{"record":{"id":"8467c87b281315a5","repo":"langchain-ai/deepagents","slug":"runloop-api-unreachable-transient-safe-to-retry","errorCode":null,"errorMessage":"Runloop API unreachable (transient — safe to retry): {e}","messagePattern":"Runloop API unreachable \\(transient — safe to retry\\): (.+?)","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"libs/partners/runloop/langchain_runloop/provider.py","lineNumber":216,"sourceCode":"\n        try:\n            if use_blueprint:\n                devbox = self._create_from_blueprint(\n                    blueprint_id=env_blueprint_id,\n                    blueprint_name=blueprint_name,\n                    dockerfile=dockerfile,\n                )\n            else:\n                devbox = self._sdk.devbox.create()\n        except (AuthenticationError, PermissionDeniedError) as e:\n            msg = (\n                \"Runloop rejected the credentials; check RUNLOOP_API_KEY \"\n                f\"(or DEEPAGENTS_CODE_RUNLOOP_API_KEY): {e}\"\n            )\n            raise RuntimeError(msg) from e\n        except (APIConnectionError, APITimeoutError) as e:\n            msg = f\"Runloop API unreachable (transient — safe to retry): {e}\"\n            raise RuntimeError(msg) from e\n        except Exception as e:\n            target = blueprint_name or env_blueprint_id or \"devbox\"\n            msg = f\"Failed to create Runloop devbox from '{target}': {e}\"\n            raise RuntimeError(msg) from e\n\n        return RunloopSandbox(devbox=devbox)\n\n    def _create_from_blueprint(\n        self,\n        *,\n        blueprint_id: str | None,\n        blueprint_name: str | None,\n        dockerfile: str,\n    ) -> Devbox:\n        if blueprint_id is not None:\n            return self._sdk.devbox.create_from_blueprint_id(blueprint_id)\n        if blueprint_name is None:\n            msg = \"Blueprint name is required when no blueprint ID is set\"","sourceCodeStart":198,"sourceCodeEnd":234,"githubUrl":"https://github.com/langchain-ai/deepagents/blob/a1af029e6e73cb17c36bff823d227747b28e91e1/libs/partners/runloop/langchain_runloop/provider.py#L198-L234","documentation":"Raised when the Runloop API raises `APIConnectionError` or `APITimeoutError` while creating a devbox or booting from a blueprint. The message explicitly states the failure is transient and safe to retry — the request never reached Runloop or timed out before a definitive answer, so no partial state needs cleanup.","triggerScenarios":"`get_or_create` create path executed while the network to api.runloop.com is down, a proxy/firewall blocks it, DNS fails, or the request exceeds the client's timeout during devbox creation or blueprint boot.","commonSituations":"Corporate proxy requiring configuration; VPN dropouts; CI runner egress restrictions; Runloop incident/outage; overly tight HTTP timeout on slow blueprint boots.","solutions":["Retry the same `get_or_create` call with exponential backoff — the error is explicitly safe to retry.","Check network egress/proxy settings (`HTTPS_PROXY`) and Runloop's status page for incidents.","Increase the HTTP client timeout if blueprint boot is slow (pass a configured client / raise timeout).","If blueprint boot times out repeatedly, boot by blueprint ID (`RUNLOOP_SANDBOX_BLUEPRINT_ID`) or use an empty devbox, then install dependencies at runtime.","Verify DNS resolution of the Runloop API host from the failing environment."],"exampleFix":"// before\nsandbox = provider.get_or_create(snapshot=\"my-bp\")  # may raise on flaky network\n\n// after\nimport time\nfor attempt in range(5):\n    try:\n        sandbox = provider.get_or_create(snapshot=\"my-bp\")\n        break\n    except RuntimeError as e:\n        if \"transient\" not in str(e) or attempt == 4:\n            raise\n        time.sleep(2 ** attempt)","handlingStrategy":"retry","validationCode":"import socket\n\ndef runloop_api_reachable(host: str = \"api.runloop.com\", timeout: float = 5.0) -> bool:\n    try:\n        socket.create_connection((host, 443), timeout=timeout).close()\n        return True\n    except OSError:\n        return False","typeGuard":null,"tryCatchPattern":"import time\n\nfor attempt in range(5):\n    try:\n        sandbox = provider.get_or_create(snapshot=\"my-bp\")\n        break\n    except RuntimeError as e:\n        if \"transient\" not in str(e):\n            raise\n        time.sleep(min(2 ** attempt, 30))\nelse:\n    raise","preventionTips":["Wrap create calls in exponential-backoff retries — the message guarantees idempotent retry safety.","Configure HTTPS_PROXY / egress rules so CI and containers can reach api.runloop.com.","Monitor Runloop's status page and gate job startup on API health checks.","Raise HTTP timeouts for long blueprint boots, or pre-build blueprints and boot by ID."],"tags":["network","timeout","transient","runloop","retryable"],"backgroundTag":"api-unreachable","analyzedSha":"a1af029e6e73cb17c36bff823d227747b28e91e1","analyzedAt":"2026-08-29T11:43:24.718Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}