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
122impl From<TypeError> for PyErr {
123    fn from(err: TypeError) -> PyErr {
124        let msg = err.to_string();
125        error!("{}", msg);
126        PyRuntimeError::new_err(msg)
127    }
128}
129
130impl From<PythonizeError> for TypeError {
131    fn from(err: PythonizeError) -> Self {
132        TypeError::Error(err.to_string())
133    }
134}
135
136impl From<PyErr> for TypeError {
137    fn from(err: PyErr) -> Self {
138        TypeError::Error(err.to_string())
139    }
140}
141
142impl<'a, 'py> From<PyClassGuardError<'a, 'py>> for TypeError {
143    fn from(err: PyClassGuardError<'a, 'py>) -> Self {
144        TypeError::Error(err.to_string())
145    }
146}
147
148impl<'a, 'py> From<pyo3::CastError<'a, 'py>> for TypeError {
149    fn from(err: pyo3::CastError<'a, 'py>) -> Self {
150        TypeError::Error(err.to_string())
151    }
152}