diff --git a/src/api/errors.rs b/src/api/errors.rs index a48025f..554a504 100644 --- a/src/api/errors.rs +++ b/src/api/errors.rs @@ -1,8 +1,16 @@ use crate::databases::postgres::errors::DbError; use crate::providers::ollama::errors::OllamaError; +use axum::Json; use axum::http::StatusCode; use axum::response::{IntoResponse, Response}; +use serde::Serialize; + +#[derive(Serialize)] +pub struct ErrorResponse { + pub error: String, + pub code: String, +} pub enum ApiError { Db(DbError), @@ -23,44 +31,84 @@ impl From for ApiError { impl IntoResponse for ApiError { fn into_response(self) -> Response { - let (status, msg) = match self { + let (status, body) = match self { ApiError::Db(db_err) => match db_err { DbError::Connection(_) => ( StatusCode::INTERNAL_SERVER_ERROR, - "database connection error".to_string(), + ErrorResponse { + error: "database connection error".to_string(), + code: "DB_CONNECTION".to_string(), + }, + ), + DbError::Timeout => ( + StatusCode::REQUEST_TIMEOUT, + ErrorResponse { + error: "database timeout".to_string(), + code: "DB_TIMEOUT".to_string(), + }, + ), + DbError::NotFound => ( + StatusCode::NOT_FOUND, + ErrorResponse { + error: "not found".to_string(), + code: "DB_NOT_FOUND".to_string(), + }, ), - DbError::Timeout => (StatusCode::REQUEST_TIMEOUT, "database timeout".to_string()), - DbError::NotFound => (StatusCode::NOT_FOUND, "not found".to_string()), }, - ApiError::Ollama(ollama_err) => match ollama_err { + ApiError::Ollama(err) => match err { OllamaError::MissingPrompt => ( StatusCode::BAD_REQUEST, - "prompt is required and cannot be empty".to_string(), + ErrorResponse { + error: "prompt is required and cannot be empty".to_string(), + code: "OLLAMA_MISSING_PROMPT".to_string(), + }, ), OllamaError::MissingModel => ( StatusCode::BAD_REQUEST, - "model is required and cannot be empty".to_string(), + ErrorResponse { + error: "model is required and cannot be empty".to_string(), + code: "OLLAMA_MISSING_MODEL".to_string(), + }, ), OllamaError::ModelNotFound(m) => ( StatusCode::UNPROCESSABLE_ENTITY, - format!("model '{m}' is not available — run `ollama pull {m}` first"), + ErrorResponse { + error: format!("model '{m}' is not available"), + code: "OLLAMA_MODEL_NOT_FOUND".to_string(), + }, ), OllamaError::MissingKeepAlive => ( StatusCode::BAD_REQUEST, - "keep alive is required and cannot be empty".to_string(), + ErrorResponse { + error: "keep_alive is required".to_string(), + code: "OLLAMA_MISSING_KEEPALIVE".to_string(), + }, + ), + OllamaError::InvalidKeepAlive(v) => ( + StatusCode::BAD_REQUEST, + ErrorResponse { + error: format!("invalid keep_alive '{v}'"), + code: "OLLAMA_INVALID_KEEPALIVE".to_string(), + }, ), - OllamaError::InvalidKeepAlive(v) => { - (StatusCode::BAD_REQUEST, format!("invalid keep_alive '{v}'")) - } OllamaError::MissingMessages => ( StatusCode::BAD_REQUEST, - "messages array with at least one user message is required".to_string(), + ErrorResponse { + error: "messages array required".to_string(), + code: "OLLAMA_MISSING_MESSAGES".to_string(), + }, + ), + OllamaError::Http(e) => ( + StatusCode::INTERNAL_SERVER_ERROR, + ErrorResponse { + error: e.to_string(), + code: "OLLAMA_HTTP_ERROR".to_string(), + }, ), - OllamaError::Http(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()), }, }; - (status, msg).into_response() + (status, Json(body)).into_response() } }