Skip to main content
Glama
exceptions.py17.6 kB
"""Structured exception classes for SelfMemory with error codes, suggestions, and debug information. This module provides a comprehensive set of exception classes that replace the generic APIError with specific, actionable exceptions. Each exception includes error codes, user-friendly suggestions, and debug information to enable better error handling and recovery in applications using SelfMemory. Example: Basic usage: try: memory.add(content, user_id=user_id) except RateLimitError as e: # Implement exponential backoff time.sleep(e.debug_info.get('retry_after', 60)) except MemoryQuotaExceededError as e: # Trigger quota upgrade flow logger.error(f"Quota exceeded: {e.error_code}") except ValidationError as e: # Return user-friendly error raise HTTPException(400, detail=e.suggestion) Advanced usage with error context: try: memory.update(memory_id, content=new_content) except MemoryNotFoundError as e: logger.warning(f"Memory {memory_id} not found: {e.message}") if e.suggestion: logger.info(f"Suggestion: {e.suggestion}") """ from typing import Any class MemoryError(Exception): """Base exception for all memory-related errors. This is the base class for all SelfMemory-specific exceptions. It provides a structured approach to error handling with error codes, contextual details, suggestions for resolution, and debug information. Attributes: message (str): Human-readable error message. error_code (str): Unique error identifier for programmatic handling. details (dict): Additional context about the error. suggestion (str): User-friendly suggestion for resolving the error. debug_info (dict): Technical debugging information. Example: raise MemoryError( message="Memory operation failed", error_code="MEM_001", details={"operation": "add", "user_id": "user123"}, suggestion="Please check your API key and try again", debug_info={"request_id": "req_456", "timestamp": "2024-01-01T00:00:00Z"} ) """ def __init__( self, message: str, error_code: str, details: dict[str, Any] | None = None, suggestion: str | None = None, debug_info: dict[str, Any] | None = None, ): """Initialize a MemoryError. Args: message: Human-readable error message. error_code: Unique error identifier. details: Additional context about the error. suggestion: User-friendly suggestion for resolving the error. debug_info: Technical debugging information. """ self.message = message self.error_code = error_code self.details = details or {} self.suggestion = suggestion self.debug_info = debug_info or {} super().__init__(self.message) def __repr__(self) -> str: return ( f"{self.__class__.__name__}(" f"message={self.message!r}, " f"error_code={self.error_code!r}, " f"details={self.details!r}, " f"suggestion={self.suggestion!r}, " f"debug_info={self.debug_info!r})" ) class AuthenticationError(MemoryError): """Raised when authentication fails. This exception is raised when API key validation fails, tokens are invalid, or authentication credentials are missing or expired. Common scenarios: - Invalid API key - Expired authentication token - Missing authentication headers - Insufficient permissions Example: raise AuthenticationError( message="Invalid API key provided", error_code="AUTH_001", suggestion="Please check your API key in the SelfMemory dashboard" ) """ pass class RateLimitError(MemoryError): """Raised when rate limits are exceeded. This exception is raised when the API rate limit has been exceeded. It includes information about retry timing and current rate limit status. The debug_info typically contains: - retry_after: Seconds to wait before retrying - limit: Current rate limit - remaining: Remaining requests in current window - reset_time: When the rate limit window resets Example: raise RateLimitError( message="Rate limit exceeded", error_code="RATE_001", suggestion="Please wait before making more requests", debug_info={"retry_after": 60, "limit": 100, "remaining": 0} ) """ pass class ValidationError(MemoryError): """Raised when input validation fails. This exception is raised when request parameters, memory content, or configuration values fail validation checks. Common scenarios: - Invalid user_id format - Missing required fields - Content too long or too short - Invalid metadata format - Malformed filters Example: raise ValidationError( message="Invalid user_id format", error_code="VAL_001", details={"field": "user_id", "value": "123", "expected": "string"}, suggestion="User ID must be a non-empty string" ) """ pass class MemoryNotFoundError(MemoryError): """Raised when a memory is not found. This exception is raised when attempting to access, update, or delete a memory that doesn't exist or is not accessible to the current user. Example: raise MemoryNotFoundError( message="Memory not found", error_code="MEM_404", details={"memory_id": "mem_123", "user_id": "user_456"}, suggestion="Please check the memory ID and ensure it exists" ) """ pass class NetworkError(MemoryError): """Raised when network connectivity issues occur. This exception is raised for network-related problems such as connection timeouts, DNS resolution failures, or service unavailability. Common scenarios: - Connection timeout - DNS resolution failure - Service temporarily unavailable - Network connectivity issues Example: raise NetworkError( message="Connection timeout", error_code="NET_001", suggestion="Please check your internet connection and try again", debug_info={"timeout": 30, "endpoint": "api.selfmemory.com"} ) """ pass class ConfigurationError(MemoryError): """Raised when client configuration is invalid. This exception is raised when the client is improperly configured, such as missing required settings or invalid configuration values. Common scenarios: - Missing API key - Invalid host URL - Incompatible configuration options - Missing required environment variables Example: raise ConfigurationError( message="API key not configured", error_code="CFG_001", suggestion="Set SELFMEMORY_API_KEY environment variable or pass api_key parameter" ) """ pass class MemoryQuotaExceededError(MemoryError): """Raised when user's memory quota is exceeded. This exception is raised when the user has reached their memory storage or usage limits. The debug_info typically contains: - current_usage: Current memory usage - quota_limit: Maximum allowed usage - usage_type: Type of quota (storage, requests, etc.) Example: raise MemoryQuotaExceededError( message="Memory quota exceeded", error_code="QUOTA_001", suggestion="Please upgrade your plan or delete unused memories", debug_info={"current_usage": 1000, "quota_limit": 1000, "usage_type": "memories"} ) """ pass class MemoryCorruptionError(MemoryError): """Raised when memory data is corrupted. This exception is raised when stored memory data is found to be corrupted, malformed, or otherwise unreadable. Example: raise MemoryCorruptionError( message="Memory data is corrupted", error_code="CORRUPT_001", details={"memory_id": "mem_123"}, suggestion="Please contact support for data recovery assistance" ) """ pass class VectorSearchError(MemoryError): """Raised when vector search operations fail. This exception is raised when vector database operations fail, such as search queries, embedding generation, or index operations. Common scenarios: - Embedding model unavailable - Vector index corruption - Search query timeout - Incompatible vector dimensions Example: raise VectorSearchError( message="Vector search failed", error_code="VEC_001", details={"query": "find similar memories", "vector_dim": 1536}, suggestion="Please try a simpler search query" ) """ pass class CacheError(MemoryError): """Raised when caching operations fail. This exception is raised when cache-related operations fail, such as cache misses, cache invalidation errors, or cache corruption. Example: raise CacheError( message="Cache operation failed", error_code="CACHE_001", details={"operation": "get", "key": "user_memories_123"}, suggestion="Cache will be refreshed automatically" ) """ pass # OSS-specific exception classes class VectorStoreError(MemoryError): """Raised when vector store operations fail. This exception is raised when vector store operations fail, such as embedding storage, similarity search, or vector operations. Example: raise VectorStoreError( message="Vector store operation failed", error_code="VECTOR_001", details={"operation": "search", "collection": "memories"}, suggestion="Please check your vector store configuration and connection" ) """ def __init__( self, message: str, error_code: str = "VECTOR_001", details: dict = None, suggestion: str = "Please check your vector store configuration and connection", debug_info: dict = None, ): super().__init__(message, error_code, details, suggestion, debug_info) class GraphStoreError(MemoryError): """Raised when graph store operations fail. This exception is raised when graph store operations fail, such as relationship creation, entity management, or graph queries. Example: raise GraphStoreError( message="Graph store operation failed", error_code="GRAPH_001", details={"operation": "create_relationship", "entity": "user_123"}, suggestion="Please check your graph store configuration and connection" ) """ def __init__( self, message: str, error_code: str = "GRAPH_001", details: dict = None, suggestion: str = "Please check your graph store configuration and connection", debug_info: dict = None, ): super().__init__(message, error_code, details, suggestion, debug_info) class EmbeddingError(MemoryError): """Raised when embedding operations fail. This exception is raised when embedding operations fail, such as text embedding generation or embedding model errors. Example: raise EmbeddingError( message="Embedding generation failed", error_code="EMBED_001", details={"text_length": 1000, "model": "openai"}, suggestion="Please check your embedding model configuration" ) """ def __init__( self, message: str, error_code: str = "EMBED_001", details: dict = None, suggestion: str = "Please check your embedding model configuration", debug_info: dict = None, ): super().__init__(message, error_code, details, suggestion, debug_info) class LLMError(MemoryError): """Raised when LLM operations fail. This exception is raised when LLM operations fail, such as text generation, completion, or model inference errors. Example: raise LLMError( message="LLM operation failed", error_code="LLM_001", details={"model": "gpt-4", "prompt_length": 500}, suggestion="Please check your LLM configuration and API key" ) """ def __init__( self, message: str, error_code: str = "LLM_001", details: dict = None, suggestion: str = "Please check your LLM configuration and API key", debug_info: dict = None, ): super().__init__(message, error_code, details, suggestion, debug_info) class DatabaseError(MemoryError): """Raised when database operations fail. This exception is raised when database operations fail, such as SQLite operations, connection issues, or data corruption. Example: raise DatabaseError( message="Database operation failed", error_code="DB_001", details={"operation": "insert", "table": "memories"}, suggestion="Please check your database configuration and connection" ) """ def __init__( self, message: str, error_code: str = "DB_001", details: dict = None, suggestion: str = "Please check your database configuration and connection", debug_info: dict = None, ): super().__init__(message, error_code, details, suggestion, debug_info) class DependencyError(MemoryError): """Raised when required dependencies are missing. This exception is raised when required dependencies are missing, such as optional packages for specific providers or features. Example: raise DependencyError( message="Required dependency missing", error_code="DEPS_001", details={"package": "kuzu", "feature": "graph_store"}, suggestion="Please install the required dependencies: pip install kuzu" ) """ def __init__( self, message: str, error_code: str = "DEPS_001", details: dict = None, suggestion: str = "Please install the required dependencies", debug_info: dict = None, ): super().__init__(message, error_code, details, suggestion, debug_info) # Mapping of HTTP status codes to specific exception classes HTTP_STATUS_TO_EXCEPTION = { 400: ValidationError, 401: AuthenticationError, 403: AuthenticationError, 404: MemoryNotFoundError, 408: NetworkError, 409: ValidationError, 413: MemoryQuotaExceededError, 422: ValidationError, 429: RateLimitError, 500: MemoryError, 502: NetworkError, 503: NetworkError, 504: NetworkError, } def create_exception_from_response( status_code: int, response_text: str, error_code: str | None = None, details: dict[str, Any] | None = None, debug_info: dict[str, Any] | None = None, ) -> MemoryError: """Create an appropriate exception based on HTTP response. This function analyzes the HTTP status code and response to create the most appropriate exception type with relevant error information. Args: status_code: HTTP status code from the response. response_text: Response body text. error_code: Optional specific error code. details: Additional error context. debug_info: Debug information. Returns: An instance of the appropriate MemoryError subclass. Example: exception = create_exception_from_response( status_code=429, response_text="Rate limit exceeded", debug_info={"retry_after": 60} ) # Returns a RateLimitError instance """ exception_class = HTTP_STATUS_TO_EXCEPTION.get(status_code, MemoryError) # Generate error code if not provided if not error_code: error_code = f"HTTP_{status_code}" # Create appropriate suggestion based on status code suggestions = { 400: "Please check your request parameters and try again", 401: "Please check your API key and authentication credentials", 403: "You don't have permission to perform this operation", 404: "The requested resource was not found", 408: "Request timed out. Please try again", 409: "Resource conflict. Please check your request", 413: "Request too large. Please reduce the size of your request", 422: "Invalid request data. Please check your input", 429: "Rate limit exceeded. Please wait before making more requests", 500: "Internal server error. Please try again later", 502: "Service temporarily unavailable. Please try again later", 503: "Service unavailable. Please try again later", 504: "Gateway timeout. Please try again later", } suggestion = suggestions.get(status_code, "Please try again later") return exception_class( message=response_text or f"HTTP {status_code} error", error_code=error_code, details=details or {}, suggestion=suggestion, debug_info=debug_info or {}, )

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/shrijayan/SelfMemory'

If you have feedback or need assistance with the MCP directory API, please join our Discord server