1use std::ffi::NulError;
2use std::num::NonZeroI32;
3use std::os::raw::c_int;
4use std::path::PathBuf;
5use std::string::FromUtf8Error;
6
7use crate::llama_batch::BatchAddError;
8
9pub type Result<TValue> = std::result::Result<TValue, LlamaCppError>;
11
12#[derive(Debug, Eq, PartialEq, thiserror::Error)]
14pub enum LlamaCppError {
15 #[error("BackendAlreadyInitialized")]
18 BackendAlreadyInitialized,
19 #[error("{0}")]
21 ChatTemplateError(#[from] ChatTemplateError),
22 #[error("{0}")]
24 DecodeError(#[from] DecodeError),
25 #[error("{0}")]
27 EncodeError(#[from] EncodeError),
28 #[error("{0}")]
30 LlamaModelLoadError(#[from] LlamaModelLoadError),
31 #[error("{0}")]
33 LlamaContextLoadError(#[from] LlamaContextLoadError),
34 #[error["{0}"]]
36 BatchAddError(#[from] BatchAddError),
37 #[error(transparent)]
39 EmbeddingError(#[from] EmbeddingsError),
40 #[error("Backend device {0} not found")]
43 BackendDeviceNotFound(usize),
44 #[error("Max devices exceeded. Max devices is {0}")]
46 MaxDevicesExceeded(usize),
47 #[error("JsonSchemaToGrammarError: {0}")]
49 JsonSchemaToGrammarError(String),
50}
51
52#[derive(Debug, Eq, PartialEq, thiserror::Error)]
54pub enum ChatTemplateError {
55 #[error("chat template not found - returned null pointer")]
57 MissingTemplate,
58
59 #[error("null byte in string {0}")]
61 NullError(#[from] NulError),
62
63 #[error(transparent)]
65 Utf8Error(#[from] std::str::Utf8Error),
66}
67
68#[derive(Debug, Eq, PartialEq, thiserror::Error)]
70pub enum MetaValError {
71 #[error("null byte in string {0}")]
73 NullError(#[from] NulError),
74
75 #[error("FromUtf8Error {0}")]
77 FromUtf8Error(#[from] FromUtf8Error),
78
79 #[error("Negative return value. Likely due to a missing index or key. Got return value: {0}")]
81 NegativeReturn(i32),
82}
83
84#[derive(Debug, Eq, PartialEq, thiserror::Error)]
86pub enum LlamaContextLoadError {
87 #[error("null reference from llama.cpp")]
89 NullReturn,
90}
91
92#[derive(Debug, Eq, PartialEq, thiserror::Error)]
94pub enum DecodeError {
95 #[error("Decode Error 1: NoKvCacheSlot")]
97 NoKvCacheSlot,
98 #[error("Decode Error -1: n_tokens == 0")]
100 NTokensZero,
101 #[error("Decode Error {0}: unknown")]
103 Unknown(c_int),
104}
105
106#[derive(Debug, Eq, PartialEq, thiserror::Error)]
108pub enum EncodeError {
109 #[error("Encode Error 1: NoKvCacheSlot")]
111 NoKvCacheSlot,
112 #[error("Encode Error -1: n_tokens == 0")]
114 NTokensZero,
115 #[error("Encode Error {0}: unknown")]
117 Unknown(c_int),
118}
119
120#[derive(Debug, Eq, PartialEq, thiserror::Error)]
122pub enum EmbeddingsError {
123 #[error("Embeddings weren't enabled in the context options")]
125 NotEnabled,
126 #[error("Logits were not enabled for the given token")]
128 LogitsNotEnabled,
129 #[error("Can't use sequence embeddings with a model supporting only LLAMA_POOLING_TYPE_NONE")]
131 NonePoolType,
132 #[error("Invalid embedding dimension: {0}")]
134 InvalidEmbeddingDimension(#[source] std::num::TryFromIntError),
135}
136
137#[derive(Debug, Eq, PartialEq, thiserror::Error)]
139pub enum LogitsError {
140 #[error("logits data pointer is null")]
142 NullLogits,
143 #[error("logit for token index {0} is not initialized")]
145 TokenNotInitialized(i32),
146 #[error("token index {token_index} exceeds context size {context_size}")]
148 TokenIndexExceedsContext {
149 token_index: u32,
151 context_size: u32,
153 },
154 #[error("n_vocab does not fit into usize: {0}")]
156 VocabSizeOverflow(#[source] std::num::TryFromIntError),
157 #[error("token_index does not fit into u32: {0}")]
159 TokenIndexOverflow(#[source] std::num::TryFromIntError),
160}
161
162#[derive(Debug, Eq, PartialEq, thiserror::Error)]
164pub enum GrammarError {
165 #[error("Grammar root not found in grammar string")]
167 RootNotFound,
168 #[error("Trigger word contains null bytes: {0}")]
170 TriggerWordNullBytes(NulError),
171 #[error("Grammar string or root contains null bytes: {0}")]
173 GrammarNullBytes(NulError),
174 #[error("String contains null bytes: {0}")]
176 NulError(#[from] NulError),
177 #[error("Grammar call returned null")]
179 NullGrammar,
180 #[error("Integer overflow: {0}")]
182 IntegerOverflow(String),
183 #[error("llguidance error: {0}")]
185 LlguidanceError(String),
186}
187
188#[derive(Debug, Eq, PartialEq, thiserror::Error)]
190pub enum SamplingError {
191 #[error("Integer overflow: {0}")]
193 IntegerOverflow(String),
194}
195
196impl From<NonZeroI32> for DecodeError {
198 fn from(value: NonZeroI32) -> Self {
199 match value.get() {
200 1 => Self::NoKvCacheSlot,
201 -1 => Self::NTokensZero,
202 error_code => Self::Unknown(error_code),
203 }
204 }
205}
206
207impl From<NonZeroI32> for EncodeError {
209 fn from(value: NonZeroI32) -> Self {
210 match value.get() {
211 1 => Self::NoKvCacheSlot,
212 -1 => Self::NTokensZero,
213 error_code => Self::Unknown(error_code),
214 }
215 }
216}
217
218#[derive(Debug, Eq, PartialEq, thiserror::Error)]
220pub enum LlamaModelLoadError {
221 #[error("null byte in string {0}")]
223 NullError(#[from] NulError),
224 #[error("null result from llama cpp")]
226 NullResult,
227 #[error("failed to convert path {0} to str")]
229 PathToStrError(PathBuf),
230 #[error("model file not found: {0}")]
232 FileNotFound(PathBuf),
233}
234
235#[derive(Debug, Eq, PartialEq, thiserror::Error)]
237pub enum LlamaLoraAdapterInitError {
238 #[error("null byte in string {0}")]
240 NullError(#[from] NulError),
241 #[error("null result from llama cpp")]
243 NullResult,
244 #[error("failed to convert path {0} to str")]
246 PathToStrError(PathBuf),
247 #[error("adapter file not found: {0}")]
249 FileNotFound(PathBuf),
250}
251
252#[derive(Debug, Eq, PartialEq, thiserror::Error)]
254pub enum LlamaLoraAdapterSetError {
255 #[error("error code from llama cpp")]
257 ErrorResult(i32),
258}
259
260#[derive(Debug, Eq, PartialEq, thiserror::Error)]
262pub enum LlamaLoraAdapterRemoveError {
263 #[error("error code from llama cpp")]
265 ErrorResult(i32),
266}
267
268#[derive(Debug, thiserror::Error, Clone)]
270#[non_exhaustive]
271pub enum TokenToStringError {
272 #[error("Unknown Token Type")]
274 UnknownTokenType,
275 #[error("Insufficient Buffer Space {0}")]
277 InsufficientBufferSpace(c_int),
278 #[error("FromUtf8Error {0}")]
280 FromUtf8Error(#[from] FromUtf8Error),
281 #[error("Integer conversion error: {0}")]
283 IntConversionError(#[from] std::num::TryFromIntError),
284}
285
286#[derive(Debug, thiserror::Error)]
288pub enum StringToTokenError {
289 #[error("{0}")]
291 NulError(#[from] NulError),
292 #[error("{0}")]
293 CIntConversionError(#[from] std::num::TryFromIntError),
295}
296
297#[derive(Debug, thiserror::Error)]
299pub enum NewLlamaChatMessageError {
300 #[error("{0}")]
302 NulError(#[from] NulError),
303}
304
305#[derive(Debug, thiserror::Error)]
307pub enum ApplyChatTemplateError {
308 #[error("{0}")]
310 NulError(#[from] NulError),
311 #[error("{0}")]
313 FromUtf8Error(#[from] FromUtf8Error),
314 #[error("null result from llama.cpp")]
316 NullResult,
317 #[error("ffi error {0}")]
319 FfiError(i32),
320 #[error("invalid grammar trigger data")]
322 InvalidGrammarTriggerType,
323 #[error("Integer conversion error: {0}")]
325 IntConversionError(#[from] std::num::TryFromIntError),
326}
327
328#[derive(Debug, thiserror::Error)]
330pub enum ChatParseError {
331 #[error("{0}")]
333 NulError(#[from] NulError),
334 #[error("{0}")]
336 Utf8Error(#[from] FromUtf8Error),
337 #[error("null result from llama.cpp")]
339 NullResult,
340 #[error("ffi error {0}")]
342 FfiError(i32),
343}
344
345#[derive(Debug, thiserror::Error)]
347pub enum SamplerAcceptError {
348 #[error("ffi error {0}")]
350 FfiError(i32),
351}
352
353#[derive(Debug, Eq, PartialEq, thiserror::Error)]
355pub enum ModelParamsError {
356 #[error("No available slot in override vector")]
358 NoAvailableSlot,
359 #[error("Override slot is not empty")]
361 SlotNotEmpty,
362 #[error("Invalid character in key: byte {byte}, {reason}")]
364 InvalidCharacterInKey {
365 byte: u8,
367 reason: String,
369 },
370}
371
372#[derive(Debug, Eq, PartialEq, thiserror::Error)]
374pub enum TokenSamplingError {
375 #[error("No token was selected by the sampler")]
377 NoTokenSelected,
378}
379
380#[cfg(test)]
381mod tests {
382 use std::num::NonZeroI32;
383
384 use super::{DecodeError, EncodeError};
385
386 #[test]
387 fn decode_error_no_kv_cache_slot() {
388 let error = DecodeError::from(NonZeroI32::new(1).expect("1 is non-zero"));
389
390 assert_eq!(error, DecodeError::NoKvCacheSlot);
391 assert_eq!(error.to_string(), "Decode Error 1: NoKvCacheSlot");
392 }
393
394 #[test]
395 fn decode_error_n_tokens_zero() {
396 let error = DecodeError::from(NonZeroI32::new(-1).expect("-1 is non-zero"));
397
398 assert_eq!(error, DecodeError::NTokensZero);
399 assert_eq!(error.to_string(), "Decode Error -1: n_tokens == 0");
400 }
401
402 #[test]
403 fn decode_error_unknown() {
404 let error = DecodeError::from(NonZeroI32::new(42).expect("42 is non-zero"));
405
406 assert_eq!(error, DecodeError::Unknown(42));
407 assert_eq!(error.to_string(), "Decode Error 42: unknown");
408 }
409
410 #[test]
411 fn encode_error_no_kv_cache_slot() {
412 let error = EncodeError::from(NonZeroI32::new(1).expect("1 is non-zero"));
413
414 assert_eq!(error, EncodeError::NoKvCacheSlot);
415 assert_eq!(error.to_string(), "Encode Error 1: NoKvCacheSlot");
416 }
417
418 #[test]
419 fn encode_error_n_tokens_zero() {
420 let error = EncodeError::from(NonZeroI32::new(-1).expect("-1 is non-zero"));
421
422 assert_eq!(error, EncodeError::NTokensZero);
423 assert_eq!(error.to_string(), "Encode Error -1: n_tokens == 0");
424 }
425
426 #[test]
427 fn encode_error_unknown() {
428 let error = EncodeError::from(NonZeroI32::new(99).expect("99 is non-zero"));
429
430 assert_eq!(error, EncodeError::Unknown(99));
431 assert_eq!(error.to_string(), "Encode Error 99: unknown");
432 }
433}