gent/errors/
mod.rs

1//! Error types for the GENT programming language
2
3use thiserror::Error;
4
5mod reporter;
6pub use reporter::ErrorReporter;
7
8/// Source location span for error reporting
9#[derive(Debug, Clone, PartialEq, Eq, Default)]
10pub struct Span {
11    pub start: usize,
12    pub end: usize,
13}
14
15impl Span {
16    /// Create a new span with start and end positions
17    pub fn new(start: usize, end: usize) -> Self {
18        Self { start, end }
19    }
20}
21
22/// All possible errors in the GENT language
23#[derive(Debug, Error)]
24pub enum GentError {
25    /// Syntax error during parsing
26    #[error("Syntax error at {span:?}: {message}")]
27    SyntaxError { message: String, span: Span },
28
29    /// Unexpected token during parsing
30    #[error("Unexpected token: expected {expected}, found {found}")]
31    UnexpectedToken {
32        expected: String,
33        found: String,
34        span: Span,
35    },
36
37    /// Reference to undefined agent
38    #[error("Undefined agent: '{name}'")]
39    UndefinedAgent { name: String, span: Span },
40
41    /// Agent missing a required field
42    #[error("Agent '{agent}' missing required field: '{field}'")]
43    MissingAgentField {
44        agent: String,
45        field: String,
46        span: Span,
47    },
48
49    /// Type mismatch error
50    #[error("Type error: expected {expected}, got {got}")]
51    TypeError {
52        expected: String,
53        got: String,
54        span: Span,
55    },
56
57    /// LLM communication error
58    #[error("LLM error: {message}")]
59    LLMError { message: String },
60
61    /// File read error
62    #[error("Could not read file '{path}': {source}")]
63    FileReadError {
64        path: String,
65        #[source]
66        source: std::io::Error,
67    },
68
69    /// API request failed
70    #[error("API error: {message}")]
71    ApiError { message: String },
72
73    /// Missing API key
74    #[error("Missing API key for {provider}. Set {provider}_API_KEY environment variable.")]
75    MissingApiKey { provider: String },
76
77    /// Agent exceeded maximum steps
78    #[error("Agent exceeded maximum steps ({limit})")]
79    MaxStepsExceeded { limit: u32 },
80
81    /// Parallel execution timeout
82    #[error("Parallel block '{name}' timed out after {timeout_ms}ms")]
83    ParallelTimeout { name: String, timeout_ms: u64 },
84
85    /// Unknown tool referenced
86    #[error("Unknown tool: '{name}'")]
87    UnknownTool { name: String, span: Span },
88
89    /// Tool execution failed
90    #[error("Tool '{tool}' failed: {message}")]
91    ToolError { tool: String, message: String },
92
93    /// Undefined variable reference
94    #[error("Undefined variable: {name}")]
95    UndefinedVariable { name: String, span: Span },
96
97    /// Undefined property access
98    #[error("Undefined property: {property} on {type_name}")]
99    UndefinedProperty {
100        property: String,
101        type_name: String,
102        span: Span,
103    },
104
105    /// Array/List index out of bounds
106    #[error("Index out of bounds: {index} (length: {length})")]
107    IndexOutOfBounds {
108        index: i64,
109        length: usize,
110        span: Span,
111    },
112
113    /// Attempt to index a non-indexable type
114    #[error("Cannot index into {type_name}")]
115    NotIndexable { type_name: String, span: Span },
116
117    /// Invalid operand types for binary operation
118    #[error("Invalid operand types: {left} {op} {right}")]
119    InvalidOperands {
120        op: String,
121        left: String,
122        right: String,
123        span: Span,
124    },
125
126    /// Division by zero error
127    #[error("Division by zero")]
128    DivisionByZero { span: Span },
129
130    /// Wrong number of arguments to function/tool
131    #[error("Expected {expected} arguments, got {got}")]
132    WrongArgumentCount {
133        expected: usize,
134        got: usize,
135        span: Span,
136    },
137
138    /// Type mismatch for function/tool argument
139    #[error("Type mismatch for parameter '{param}': expected {expected}, got {got}")]
140    ArgumentTypeMismatch {
141        param: String,
142        expected: String,
143        got: String,
144        span: Span,
145    },
146
147    /// Output validation failed for structured output
148    #[error("Output validation error: {message}\nExpected schema: {expected}\nGot: {got}")]
149    OutputValidationError {
150        message: String,
151        expected: String,
152        got: String,
153    },
154}
155
156impl GentError {
157    /// Get the source span if this error has one
158    pub fn span(&self) -> Option<&Span> {
159        match self {
160            GentError::SyntaxError { span, .. } => Some(span),
161            GentError::UnexpectedToken { span, .. } => Some(span),
162            GentError::UndefinedAgent { span, .. } => Some(span),
163            GentError::MissingAgentField { span, .. } => Some(span),
164            GentError::TypeError { span, .. } => Some(span),
165            GentError::UnknownTool { span, .. } => Some(span),
166            GentError::UndefinedVariable { span, .. } => Some(span),
167            GentError::UndefinedProperty { span, .. } => Some(span),
168            GentError::IndexOutOfBounds { span, .. } => Some(span),
169            GentError::NotIndexable { span, .. } => Some(span),
170            GentError::InvalidOperands { span, .. } => Some(span),
171            GentError::DivisionByZero { span } => Some(span),
172            GentError::WrongArgumentCount { span, .. } => Some(span),
173            GentError::ArgumentTypeMismatch { span, .. } => Some(span),
174            GentError::LLMError { .. } => None,
175            GentError::FileReadError { .. } => None,
176            GentError::ApiError { .. } => None,
177            GentError::MissingApiKey { .. } => None,
178            GentError::MaxStepsExceeded { .. } => None,
179            GentError::ParallelTimeout { .. } => None,
180            GentError::ToolError { .. } => None,
181            GentError::OutputValidationError { .. } => None,
182        }
183    }
184}
185
186/// Result type alias for GENT operations
187pub type GentResult<T> = Result<T, GentError>;