codex-memory 3.0.15

A simple memory storage service with MCP interface for Claude Desktop
Documentation
use std::fmt;

/// Enhanced error type with comprehensive error handling
#[derive(Debug)]
pub enum Error {
    Database(sqlx::Error),
    Config(String),
    Io(std::io::Error),
    Json(serde_json::Error),
    Other(String),
    // MCP-specific errors for JSON-RPC 2.0 compliance
    ParseError(String),      // -32700
    InvalidRequest(String),  // -32600
    MethodNotFound(String),  // -32601
    InvalidParams(String),   // -32602
    InternalError(String),   // -32603
    Timeout(String),         // -32603 with timeout details
    // Enhanced error types for better error handling
    ValidationError(String), // Input validation failures
    NotFound(String),       // Resource not found errors
    Conflict(String),       // Conflict errors (duplicates, etc.)
    Unauthorized(String),   // Authorization errors
    RateLimited(String),    // Rate limiting errors
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Error::Database(e) => write!(f, "Database error: {}", e),
            Error::Config(e) => write!(f, "Configuration error: {}", e),
            Error::Io(e) => write!(f, "IO error: {}", e),
            Error::Json(e) => write!(f, "JSON error: {}", e),
            Error::Other(e) => write!(f, "Error: {}", e),
            Error::ParseError(e) => write!(f, "Parse error: {}", e),
            Error::InvalidRequest(e) => write!(f, "Invalid request: {}", e),
            Error::MethodNotFound(e) => write!(f, "Method not found: {}", e),
            Error::InvalidParams(e) => write!(f, "Invalid params: {}", e),
            Error::InternalError(e) => write!(f, "Internal error: {}", e),
            Error::Timeout(e) => write!(f, "Timeout: {}", e),
            Error::ValidationError(e) => write!(f, "Validation error: {}", e),
            Error::NotFound(e) => write!(f, "Not found: {}", e),
            Error::Conflict(e) => write!(f, "Conflict: {}", e),
            Error::Unauthorized(e) => write!(f, "Unauthorized: {}", e),
            Error::RateLimited(e) => write!(f, "Rate limited: {}", e),
        }
    }
}

impl std::error::Error for Error {}

impl From<sqlx::Error> for Error {
    fn from(e: sqlx::Error) -> Self {
        Error::Database(e)
    }
}

impl From<std::io::Error> for Error {
    fn from(e: std::io::Error) -> Self {
        Error::Io(e)
    }
}

impl From<serde_json::Error> for Error {
    fn from(e: serde_json::Error) -> Self {
        Error::Json(e)
    }
}

impl From<anyhow::Error> for Error {
    fn from(e: anyhow::Error) -> Self {
        Error::Other(e.to_string())
    }
}

impl From<url::ParseError> for Error {
    fn from(e: url::ParseError) -> Self {
        Error::Config(format!("Invalid URL: {}", e))
    }
}

impl From<uuid::Error> for Error {
    fn from(e: uuid::Error) -> Self {
        Error::InvalidParams(format!("Invalid UUID: {}", e))
    }
}

impl From<regex::Error> for Error {
    fn from(e: regex::Error) -> Self {
        Error::InternalError(format!("Regex error: {}", e))
    }
}

impl From<tokio::time::error::Elapsed> for Error {
    fn from(_: tokio::time::error::Elapsed) -> Self {
        Error::Timeout("Operation timed out".to_string())
    }
}

impl Error {
    /// Get the appropriate JSON-RPC 2.0 error code for this error
    pub fn json_rpc_code(&self) -> i32 {
        match self {
            Error::ParseError(_) => -32700,        // Parse error
            Error::InvalidRequest(_) => -32600,    // Invalid Request
            Error::MethodNotFound(_) => -32601,    // Method not found
            Error::InvalidParams(_) | Error::ValidationError(_) => -32602, // Invalid params
            Error::InternalError(_) | Error::Timeout(_) => -32603, // Internal error
            Error::Database(_) => -32603,          // Internal error (database)
            Error::Config(_) => -32603,            // Internal error (config)
            Error::Io(_) => -32603,                // Internal error (I/O)
            Error::Json(_) => -32700,              // Parse error (JSON)
            Error::Other(_) => -32603,             // Internal error (generic)
            Error::NotFound(_) => -32001,          // Custom: Resource not found
            Error::Conflict(_) => -32002,          // Custom: Resource conflict
            Error::Unauthorized(_) => -32003,     // Custom: Unauthorized access
            Error::RateLimited(_) => -32004,       // Custom: Rate limit exceeded
        }
    }

    /// Create a JSON-RPC 2.0 compliant error response
    pub fn to_json_rpc_error(&self, id: Option<serde_json::Value>) -> serde_json::Value {
        serde_json::json!({
            "jsonrpc": "2.0",
            "id": id,
            "error": {
                "code": self.json_rpc_code(),
                "message": self.to_string()
            }
        })
    }
}

pub type Result<T> = std::result::Result<T, Error>;