Skip to main content

feagi_services/types/
errors.rs

1// Copyright 2025 Neuraville Inc.
2// SPDX-License-Identifier: Apache-2.0
3
4/*!
5Service layer error types.
6
7Transport-agnostic errors that can be mapped to HTTP status codes,
8ZMQ error codes, or embedded error codes by adapters.
9
10Copyright 2025 Neuraville Inc.
11Licensed under the Apache License, Version 2.0
12*/
13
14use thiserror::Error;
15
16/// Service layer errors (transport-agnostic)
17#[derive(Error, Debug, Clone)]
18pub enum ServiceError {
19    /// Resource not found (404 in HTTP, NOT_FOUND in ZMQ)
20    #[error("Not found: {resource} with id '{id}'")]
21    NotFound { resource: String, id: String },
22
23    /// Invalid input parameters (400 in HTTP, BAD_REQUEST in ZMQ)
24    #[error("Invalid input: {0}")]
25    InvalidInput(String),
26
27    /// Resource already exists (409 in HTTP, CONFLICT in ZMQ)
28    #[error("Already exists: {resource} with id '{id}'")]
29    AlreadyExists { resource: String, id: String },
30
31    /// Operation not permitted (403 in HTTP, FORBIDDEN in ZMQ)
32    #[error("Operation not permitted: {0}")]
33    Forbidden(String),
34
35    /// Internal service error (500 in HTTP, INTERNAL_ERROR in ZMQ)
36    #[error("Internal error: {0}")]
37    Internal(String),
38
39    /// Backend error (BDU, NPU, Evo)
40    #[error("Backend error: {0}")]
41    Backend(String),
42
43    /// State inconsistency
44    #[error("State error: {0}")]
45    StateError(String),
46
47    /// Invalid state for operation (e.g., trying to pause when not running)
48    #[error("Invalid state: {0}")]
49    InvalidState(String),
50
51    /// Not yet implemented
52    #[error("Not implemented: {0}")]
53    NotImplemented(String),
54}
55
56/// Result type for service operations
57pub type ServiceResult<T> = Result<T, ServiceError>;
58
59// ============================================================================
60// ERROR CONVERSIONS FROM BACKEND
61// ============================================================================
62
63impl From<feagi_npu_neural::types::FeagiError> for ServiceError {
64    fn from(err: feagi_npu_neural::types::FeagiError) -> Self {
65        match err {
66            feagi_npu_neural::types::FeagiError::CorticalAreaNotFound(_) => {
67                ServiceError::NotFound {
68                    resource: "CorticalArea".to_string(),
69                    id: err.to_string(),
70                }
71            }
72            feagi_npu_neural::types::FeagiError::InvalidArea(msg) => {
73                ServiceError::InvalidInput(msg)
74            }
75            feagi_npu_neural::types::FeagiError::InvalidRegion(msg) => {
76                ServiceError::InvalidInput(msg)
77            }
78            _ => ServiceError::Backend(err.to_string()),
79        }
80    }
81}
82
83impl From<feagi_structures::FeagiDataError> for ServiceError {
84    fn from(err: feagi_structures::FeagiDataError) -> Self {
85        ServiceError::InvalidInput(err.to_string())
86    }
87}
88
89impl From<feagi_brain_development::BduError> for ServiceError {
90    fn from(err: feagi_brain_development::BduError) -> Self {
91        match err {
92            feagi_brain_development::BduError::InvalidArea(msg) => ServiceError::InvalidInput(msg),
93            feagi_brain_development::BduError::InvalidGenome(msg) => {
94                ServiceError::InvalidInput(msg)
95            }
96            feagi_brain_development::BduError::InvalidMorphology(msg) => {
97                ServiceError::InvalidInput(msg)
98            }
99            _ => ServiceError::Backend(err.to_string()),
100        }
101    }
102}
103
104impl From<feagi_evolutionary::EvoError> for ServiceError {
105    fn from(err: feagi_evolutionary::EvoError) -> Self {
106        match err {
107            feagi_evolutionary::EvoError::InvalidGenome(msg) => ServiceError::InvalidInput(msg),
108            feagi_evolutionary::EvoError::InvalidArea(msg) => ServiceError::InvalidInput(msg),
109            _ => ServiceError::Backend(err.to_string()),
110        }
111    }
112}