orka/
error.rs

1// orka_core/src/error.rs
2use anyhow::Error as AnyhowError;
3use thiserror::Error;
4
5#[derive(Debug, Error)]
6pub enum OrkaError {
7    #[error("Step not found: {step_name}")]
8    StepNotFound { step_name: String },
9
10    #[error("Handler missing for non-optional step: {step_name}")]
11    HandlerMissing { step_name: String },
12
13    #[error("Extractor failed for step '{step_name}'. Source: {source}")]
14    ExtractorFailure {
15        step_name: String,
16        #[source]
17        source: AnyhowError,
18    },
19
20    #[error("Pipeline provider failed for conditional scope in step '{step_name}'. Source: {source}")]
21    PipelineProviderFailure {
22        step_name: String,
23        #[source]
24        source: AnyhowError,
25    },
26
27    #[error("Type mismatch during context downcast (expected {expected_type}, step: '{step_name}')")]
28    TypeMismatch {
29        step_name: String,
30        expected_type: String,
31    },
32
33    #[error("Error in user-provided handler or external operation. Source: {source}")]
34    HandlerError {
35        #[source]
36        source: AnyhowError,
37    },
38    
39    #[error("Configuration error for step '{step_name}': {message}")]
40    ConfigurationError { step_name: String, message: String },
41
42    #[error("Internal Orka error: {0}")]
43    Internal(String),
44    // Add NoConditionalScopeMatched if it's used by the builder
45    #[error("No conditional scope's condition matched for step '{step_name}'")]
46    NoConditionalScopeMatched { step_name: String },
47}
48
49// This is the key conversion Orka provides for external errors.
50impl From<AnyhowError> for OrkaError {
51  fn from(err: AnyhowError) -> Self {
52    // Check if the anyhow::Error is already wrapping an OrkaError
53    // to avoid OrkaError(HandlerError(OrkaError(...)))
54    if let Some(orka_err) = err.downcast_ref::<OrkaError>() {
55        // This requires OrkaError to be Clone, or to reconstruct.
56        // For now, let's assume we want to avoid direct cloning if not necessary
57        // and just re-wrap for simplicity, or handle specific variants.
58        // A simple re-wrap:
59        // return OrkaError::HandlerError { source: err }; // This might be fine.
60
61        // If OrkaError is not Clone, we can't just return *orka_err.
62        // A common pattern is to stringify and wrap in Internal, or just re-wrap as HandlerError.
63        // Given HandlerError takes anyhow::Error, simply returning it is often best.
64        return OrkaError::HandlerError { source: err };
65    }
66    OrkaError::HandlerError { source: err }
67  }
68}
69
70pub type OrkaResult<T, E = OrkaError> = std::result::Result<T, E>;