Files
Analytical_engine_backend/venv/Lib/site-packages/langsmith/sandbox/_exceptions.py
2026-05-11 12:36:20 +05:30

287 lines
8.5 KiB
Python

"""Custom exceptions for the sandbox client.
All sandbox exceptions extend LangSmithError for unified error handling.
The exceptions are organized by error type rather than resource type,
with a resource_type attribute for specific handling when needed.
"""
from __future__ import annotations
from typing import Optional
from langsmith.utils import LangSmithError
class SandboxClientError(LangSmithError):
"""Base exception for sandbox client errors."""
pass
# =============================================================================
# Connection and Authentication Errors
# =============================================================================
class SandboxAPIError(SandboxClientError):
"""Raised when the API endpoint returns an unexpected error.
For example, this is raised for wrong URL or path.
"""
pass
class SandboxAuthenticationError(SandboxClientError):
"""Raised when authentication fails (invalid or missing API key)."""
pass
class SandboxConnectionError(SandboxClientError):
"""Raised when connection to the sandbox server fails."""
pass
class SandboxServerReloadError(SandboxConnectionError):
"""Raised when the server sends a 1001 Going Away close frame.
This indicates a server hot-reload, not a true connection failure.
The command is still running on the server.
This is a subclass of SandboxConnectionError, so the auto-reconnect
logic in CommandHandle catches it along with all other
connection errors. The distinction matters for retry strategy:
SandboxServerReloadError triggers immediate reconnect (no backoff),
while other SandboxConnectionError triggers exponential backoff.
Users typically never see this exception — it's handled internally.
"""
pass
# =============================================================================
# Resource Errors (type-based, with resource_type attribute)
# =============================================================================
class ResourceNotFoundError(SandboxClientError):
"""Raised when a resource is not found.
Attributes:
resource_type: Type of resource (sandbox, template, volume, pool, file).
"""
def __init__(self, message: str, resource_type: Optional[str] = None):
"""Initialize the error."""
super().__init__(message)
self.resource_type = resource_type
class ResourceTimeoutError(SandboxClientError):
"""Raised when an operation times out.
Attributes:
resource_type: Type of resource (sandbox, volume, pool).
last_status: The last known status before timeout (for sandboxes).
"""
def __init__(
self,
message: str,
resource_type: Optional[str] = None,
last_status: Optional[str] = None,
):
"""Initialize the error."""
super().__init__(message)
self.resource_type = resource_type
self.last_status = last_status
def __str__(self) -> str:
"""Return string representation."""
base = super().__str__()
if self.last_status:
return f"{base} (last_status: {self.last_status})"
return base
class ResourceInUseError(SandboxClientError):
"""Raised when deleting a resource that is still in use.
Attributes:
resource_type: Type of resource (template, volume).
"""
def __init__(self, message: str, resource_type: Optional[str] = None):
"""Initialize the error."""
super().__init__(message)
self.resource_type = resource_type
class ResourceAlreadyExistsError(SandboxClientError):
"""Raised when creating a resource that already exists.
Attributes:
resource_type: Type of resource (e.g., pool).
"""
def __init__(self, message: str, resource_type: Optional[str] = None):
"""Initialize the error."""
super().__init__(message)
self.resource_type = resource_type
class ResourceNameConflictError(SandboxClientError):
"""Raised when updating a resource name to one that already exists.
Attributes:
resource_type: Type of resource (volume, template, pool, sandbox).
"""
def __init__(self, message: str, resource_type: Optional[str] = None):
"""Initialize the error."""
super().__init__(message)
self.resource_type = resource_type
# =============================================================================
# Validation and Quota Errors
# =============================================================================
class ValidationError(SandboxClientError):
"""Raised when request validation fails.
This includes:
- Resource values exceeding server-defined limits (CPU, memory, storage)
- Invalid resource units
- Invalid name formats
- Pool validation failures (e.g., template has volumes)
Attributes:
field: The field that failed validation (e.g., "cpu", "memory").
details: List of validation error details from the API.
error_type: Machine-readable error type from the API.
"""
def __init__(
self,
message: str,
field: Optional[str] = None,
details: Optional[list[dict]] = None,
error_type: Optional[str] = None,
):
"""Initialize the error."""
super().__init__(message)
self.field = field
self.details = details or []
self.error_type = error_type
class QuotaExceededError(SandboxClientError):
"""Raised when organization quota limits are exceeded.
Users should contact support@langchain.dev to increase quotas.
Attributes:
quota_type: Type of quota exceeded (e.g., "sandbox_count", "cpu").
"""
def __init__(self, message: str, quota_type: Optional[str] = None):
"""Initialize the error."""
super().__init__(message)
self.quota_type = quota_type
# =============================================================================
# Resource Creation Errors
# =============================================================================
class ResourceCreationError(SandboxClientError):
"""Raised when resource provisioning fails.
Attributes:
resource_type: Type of resource (sandbox, volume, pool).
error_type: Machine-readable error type (ImagePull, CrashLoop,
SandboxConfig, Unschedulable, VolumeProvisioning).
"""
def __init__(
self,
message: str,
resource_type: Optional[str] = None,
error_type: Optional[str] = None,
):
"""Initialize the error."""
super().__init__(message)
self.resource_type = resource_type
self.error_type = error_type
def __str__(self) -> str:
"""Return string representation."""
if self.error_type:
return f"{super().__str__()} [{self.error_type}]"
return super().__str__()
# =============================================================================
# Sandbox Operation Errors (runtime errors during sandbox interaction)
# =============================================================================
class DataplaneNotConfiguredError(SandboxClientError):
"""Raised when dataplane_url is not available for the sandbox.
This occurs when the sandbox-router URL is not configured for the cluster.
"""
pass
class SandboxNotReadyError(SandboxClientError):
"""Raised when attempting to interact with a sandbox that is not ready."""
pass
class SandboxOperationError(SandboxClientError):
"""Raised when a sandbox operation fails (run, read, write).
Attributes:
operation: The operation that failed (command, read, write).
error_type: Machine-readable error type from the API.
"""
def __init__(
self,
message: str,
operation: Optional[str] = None,
error_type: Optional[str] = None,
):
"""Initialize the error."""
super().__init__(message)
self.operation = operation
self.error_type = error_type
def __str__(self) -> str:
"""Return string representation."""
if self.error_type:
return f"{super().__str__()} [{self.error_type}]"
return super().__str__()
class CommandTimeoutError(SandboxOperationError):
"""Raised when a command exceeds its timeout.
Attributes:
timeout: The timeout value in seconds that was exceeded.
"""
def __init__(self, message: str, timeout: Optional[int] = None):
"""Initialize the error."""
super().__init__(message, operation="command", error_type="CommandTimeout")
self.timeout = timeout