diff --git a/docs/sandbox.md b/docs/sandbox.md
index 7aef7af3..80705d9e 100644
--- a/docs/sandbox.md
+++ b/docs/sandbox.md
@@ -2143,6 +2143,16 @@ class SandboxTimeoutError(SandboxError)
Raised when a sandbox operation times out
+
+
+## SandboxDeploymentError Objects
+
+```python
+class SandboxDeploymentError(SandboxError)
+```
+
+Raised when a sandbox deployment reaches an error state
+
# koyeb/sandbox.executor\_client
diff --git a/koyeb/sandbox/__init__.py b/koyeb/sandbox/__init__.py
index e3106218..b4b3d58a 100644
--- a/koyeb/sandbox/__init__.py
+++ b/koyeb/sandbox/__init__.py
@@ -17,7 +17,7 @@
)
from .filesystem import FileInfo, SandboxFilesystem
from .sandbox import AsyncSandbox, ExposedPort, ProcessInfo, Sandbox
-from .utils import SandboxError, SandboxTimeoutError
+from .utils import SandboxDeploymentError, SandboxError, SandboxTimeoutError
__all__ = [
"Sandbox",
@@ -27,6 +27,7 @@
"AsyncSandboxExecutor",
"FileInfo",
"SandboxStatus",
+ "SandboxDeploymentError",
"SandboxError",
"SandboxTimeoutError",
"CommandResult",
diff --git a/koyeb/sandbox/sandbox.py b/koyeb/sandbox/sandbox.py
index 7213d628..aa9cb6d4 100644
--- a/koyeb/sandbox/sandbox.py
+++ b/koyeb/sandbox/sandbox.py
@@ -24,6 +24,7 @@
from .utils import (
DEFAULT_INSTANCE_WAIT_TIMEOUT,
DEFAULT_POLL_INTERVAL,
+ SandboxDeploymentError,
SandboxError,
SandboxTimeoutError,
async_wrapper,
@@ -388,12 +389,20 @@ def get_from_id(
sandbox_secret=sandbox_secret,
)
+ _DEPLOYMENT_ERROR_STATUSES = {
+ DeploymentStatus.ERROR,
+ DeploymentStatus.ERRORING,
+ }
+
def _is_deployment_healthy(self) -> bool:
"""
Check if the sandbox deployment status is HEALTHY via the API.
Returns:
bool: True if the deployment status is HEALTHY, False otherwise
+
+ Raises:
+ SandboxDeploymentError: If the deployment has reached a terminal error state
"""
try:
_, services_api, _, _, deployments_api = get_api_client(self.api_token)
@@ -404,7 +413,14 @@ def _is_deployment_healthy(self) -> bool:
return False
deployment_response = deployments_api.get_deployment(deployment_id)
status = deployment_response.deployment.status
+ if status in self._DEPLOYMENT_ERROR_STATUSES:
+ raise SandboxDeploymentError(
+ f"Sandbox '{self.name}' deployment reached status {status.value}. "
+ f"The sandbox will not become ready."
+ )
return status == DeploymentStatus.HEALTHY
+ except SandboxDeploymentError:
+ raise
except Exception:
return False
diff --git a/koyeb/sandbox/utils.py b/koyeb/sandbox/utils.py
index dd1d46b5..0b942b31 100644
--- a/koyeb/sandbox/utils.py
+++ b/koyeb/sandbox/utils.py
@@ -486,3 +486,7 @@ class SandboxError(Exception):
class SandboxTimeoutError(SandboxError):
"""Raised when a sandbox operation times out"""
+
+
+class SandboxDeploymentError(SandboxError):
+ """Raised when a sandbox deployment reaches an error state"""