Skip to main content

potato_type/
error.rs

1use pyo3::exceptions::PyRuntimeError;
2use pyo3::pyclass::PyClassGuardError;
3use pyo3::PyErr;
4use pythonize::PythonizeError;
5use thiserror::Error;
6use tracing::error;
7
8#[derive(Error, Debug)]
9pub enum TypeError {
10    #[error("Error: {0}")]
11    Error(String),
12
13    #[error("Unknown provider: {0}")]
14    UnknownProviderError(String),
15
16    #[error("Unknown model: {0}")]
17    UnknownModelError(String),
18
19    #[error("{0}")]
20    InvalidInput(String),
21
22    #[error(transparent)]
23    UtilError(#[from] potato_util::UtilError),
24
25    #[error(transparent)]
26    SerdeError(#[from] serde_json::Error),
27
28    #[error(transparent)]
29    StdError(#[from] std::io::Error),
30
31    #[error("Failed to create GeminiEmbeddingConfig: {0}")]
32    GeminiEmbeddingConfigError(String),
33
34    #[error("Invalid media type: {0}")]
35    InvalidMediaType(String),
36
37    #[error("Unsupported prompt content type")]
38    UnsupportedTypeError,
39
40    #[error("Cannot bind non-string content")]
41    CannotBindNonStringContent,
42
43    #[error("Failed to serialize Python object: {0}")]
44    PySerializationError(String),
45
46    #[error("Content type is not supported")]
47    UnsupportedContentType,
48
49    #[error("Invalid model settings provided. ModelSettings expects either OpenAIChatSettings, GeminiSettings, or AnthropicSettings.")]
50    InvalidModelSettings,
51
52    #[error("Expected string, Message, or list of messages")]
53    MessageParseError,
54
55    #[error("Invalid message type in list. Received: {0}")]
56    InvalidMessageTypeInList(String),
57
58    #[error("Either 'auto_mode' or 'manual_mode' must be provided, but not both.")]
59    MissingRoutingConfigMode,
60
61    #[error("Invalid data type for Part. Expected String, Blob, FileData, FunctionCall, FunctionResponse, ExecutableCode, or CodeExecutionResult. Got: {0}")]
62    InvalidDataType(String),
63
64    #[error("Invalid list type for Part. Expected a list of Strings or a list of Message objects. Got: {0}")]
65    InvalidListType(String),
66
67    #[error("Parts must be a string, Part, DataNum variant, or a list of these types")]
68    InvalidPartType,
69
70    #[error("Invalid ranking config provided.")]
71    InvalidRankingConfig,
72
73    #[error("Invalid retrieval source provided.")]
74    InvalidRetrievalSource,
75
76    #[error("Invalid authentication configuration provided.")]
77    InvalidAuthConfig,
78
79    #[error("Invalid OAuth configuration provided.")]
80    InvalidOauthConfig,
81
82    #[error("Invalid OIDC configuration provided.")]
83    InvalidOidcConfig,
84
85    #[error("More than one system instruction provided where only one is allowed.")]
86    MoreThanOneSystemInstruction,
87
88    #[error("Invalid request type for Anthropic provider.")]
89    InvalidRequestTypeForAnthropic,
90
91    #[error("Invalid request type for Gemini provider.")]
92    InvalidRequestTypeForGemini,
93
94    #[error("Invalid request type for OpenAI provider.")]
95    InvalidRequestTypeForOpenAI,
96
97    #[error("Unsupported provider for request creation.")]
98    UnsupportedProviderForRequestCreation,
99
100    #[error("OpenAI response content is empty.")]
101    EmptyOpenAIResponseContent,
102
103    #[error("{0}")]
104    UnsupportedConversion(String),
105
106    #[error("Cannot convert message to self")]
107    CantConvertSelf,
108
109    #[error("Unsupported provider for message conversion")]
110    UnsupportedProviderError,
111
112    #[error("Message is not an OpenAI ChatMessage")]
113    MessageIsNotOpenAIChatMessage,
114
115    #[error("Message is not a Google GeminiContent")]
116    MessageIsNotGoogleGeminiContent,
117
118    #[error("Message is not an Anthropic MessageParam")]
119    MessageIsNotAnthropicMessageParam,
120
121    #[error(transparent)]
122    SerdeYamlError(#[from] serde_yaml::Error),
123}
124
125impl From<TypeError> for PyErr {
126    fn from(err: TypeError) -> PyErr {
127        let msg = err.to_string();
128        error!("{}", msg);
129        PyRuntimeError::new_err(msg)
130    }
131}
132
133impl From<PythonizeError> for TypeError {
134    fn from(err: PythonizeError) -> Self {
135        TypeError::Error(err.to_string())
136    }
137}
138
139impl From<PyErr> for TypeError {
140    fn from(err: PyErr) -> Self {
141        TypeError::Error(err.to_string())
142    }
143}
144
145impl<'a, 'py> From<PyClassGuardError<'a, 'py>> for TypeError {
146    fn from(err: PyClassGuardError<'a, 'py>) -> Self {
147        TypeError::Error(err.to_string())
148    }
149}
150
151impl<'a, 'py> From<pyo3::CastError<'a, 'py>> for TypeError {
152    fn from(err: pyo3::CastError<'a, 'py>) -> Self {
153        TypeError::Error(err.to_string())
154    }
155}