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 2: Aborted")]
100 Aborted,
101 #[error("Decode Error -1: n_tokens == 0")]
103 NTokensZero,
104 #[error("Decode Error {0}: unknown")]
106 Unknown(c_int),
107}
108
109#[derive(Debug, Eq, PartialEq, thiserror::Error)]
111pub enum EncodeError {
112 #[error("Encode Error 1: NoKvCacheSlot")]
114 NoKvCacheSlot,
115 #[error("Encode Error -1: n_tokens == 0")]
117 NTokensZero,
118 #[error("Encode Error {0}: unknown")]
120 Unknown(c_int),
121}
122
123#[derive(Debug, Eq, PartialEq, thiserror::Error)]
125pub enum EmbeddingsError {
126 #[error("Embeddings weren't enabled in the context options")]
128 NotEnabled,
129 #[error("Logits were not enabled for the given token")]
131 LogitsNotEnabled,
132 #[error("Can't use sequence embeddings with a model supporting only LLAMA_POOLING_TYPE_NONE")]
134 NonePoolType,
135 #[error("Invalid embedding dimension: {0}")]
137 InvalidEmbeddingDimension(#[source] std::num::TryFromIntError),
138}
139
140#[derive(Debug, Eq, PartialEq, thiserror::Error)]
142pub enum LogitsError {
143 #[error("logits data pointer is null")]
145 NullLogits,
146 #[error("logit for token index {0} is not initialized")]
148 TokenNotInitialized(i32),
149 #[error("token index {token_index} exceeds context size {context_size}")]
151 TokenIndexExceedsContext {
152 token_index: u32,
154 context_size: u32,
156 },
157 #[error("n_vocab does not fit into usize: {0}")]
159 VocabSizeOverflow(#[source] std::num::TryFromIntError),
160 #[error("token_index does not fit into u32: {0}")]
162 TokenIndexOverflow(#[source] std::num::TryFromIntError),
163}
164
165#[derive(Debug, Eq, PartialEq, thiserror::Error)]
167pub enum GrammarError {
168 #[error("Grammar root not found in grammar string")]
170 RootNotFound,
171 #[error("Trigger word contains null bytes: {0}")]
173 TriggerWordNullBytes(NulError),
174 #[error("Grammar string or root contains null bytes: {0}")]
176 GrammarNullBytes(NulError),
177 #[error("String contains null bytes: {0}")]
179 NulError(#[from] NulError),
180 #[error("Grammar initialization failed: {0}")]
182 NullGrammar(String),
183 #[error("Integer overflow: {0}")]
185 IntegerOverflow(String),
186 #[error("llguidance error: {0}")]
188 LlguidanceError(String),
189}
190
191#[derive(Debug, Eq, PartialEq, thiserror::Error)]
193pub enum SamplingError {
194 #[error("Integer overflow: {0}")]
196 IntegerOverflow(String),
197}
198
199#[derive(Debug, Eq, PartialEq, thiserror::Error)]
201pub enum SampleError {
202 #[error("C++ exception during sampling: {0}")]
204 CppException(String),
205
206 #[error("Invalid argument passed to sampler")]
208 InvalidArgument,
209}
210
211impl From<NonZeroI32> for DecodeError {
213 fn from(value: NonZeroI32) -> Self {
214 match value.get() {
215 1 => Self::NoKvCacheSlot,
216 2 => Self::Aborted,
217 -1 => Self::NTokensZero,
218 error_code => Self::Unknown(error_code),
219 }
220 }
221}
222
223impl From<NonZeroI32> for EncodeError {
225 fn from(value: NonZeroI32) -> Self {
226 match value.get() {
227 1 => Self::NoKvCacheSlot,
228 -1 => Self::NTokensZero,
229 error_code => Self::Unknown(error_code),
230 }
231 }
232}
233
234#[derive(Debug, Eq, PartialEq, thiserror::Error)]
236pub enum LlamaModelLoadError {
237 #[error("null byte in string {0}")]
239 NullError(#[from] NulError),
240 #[error("null result from llama cpp")]
242 NullResult,
243 #[error("failed to convert path {0} to str")]
245 PathToStrError(PathBuf),
246 #[error("model file not found: {0}")]
248 FileNotFound(PathBuf),
249}
250
251#[derive(Debug, Eq, PartialEq, thiserror::Error)]
253pub enum LlamaLoraAdapterInitError {
254 #[error("null byte in string {0}")]
256 NullError(#[from] NulError),
257 #[error("null result from llama cpp")]
259 NullResult,
260 #[error("failed to convert path {0} to str")]
262 PathToStrError(PathBuf),
263 #[error("adapter file not found: {0}")]
265 FileNotFound(PathBuf),
266}
267
268#[derive(Debug, Eq, PartialEq, thiserror::Error)]
270pub enum LlamaLoraAdapterSetError {
271 #[error("error code from llama cpp")]
273 ErrorResult(i32),
274}
275
276#[derive(Debug, Eq, PartialEq, thiserror::Error)]
278pub enum LlamaLoraAdapterRemoveError {
279 #[error("error code from llama cpp")]
281 ErrorResult(i32),
282}
283
284#[derive(Debug, thiserror::Error, Clone)]
286#[non_exhaustive]
287pub enum TokenToStringError {
288 #[error("Unknown Token Type")]
290 UnknownTokenType,
291 #[error("Insufficient Buffer Space {0}")]
293 InsufficientBufferSpace(c_int),
294 #[error("FromUtf8Error {0}")]
296 FromUtf8Error(#[from] FromUtf8Error),
297 #[error("Integer conversion error: {0}")]
299 IntConversionError(#[from] std::num::TryFromIntError),
300}
301
302#[derive(Debug, thiserror::Error)]
304pub enum StringToTokenError {
305 #[error("{0}")]
307 NulError(#[from] NulError),
308 #[error("{0}")]
309 CIntConversionError(#[from] std::num::TryFromIntError),
311}
312
313#[derive(Debug, thiserror::Error)]
315pub enum NewLlamaChatMessageError {
316 #[error("{0}")]
318 NulError(#[from] NulError),
319}
320
321#[derive(Debug, thiserror::Error)]
323pub enum ApplyChatTemplateError {
324 #[error("{0}")]
326 NulError(#[from] NulError),
327 #[error("{0}")]
329 FromUtf8Error(#[from] FromUtf8Error),
330 #[error("null result from llama.cpp")]
332 NullResult,
333 #[error("ffi error {0}")]
335 FfiError(i32),
336 #[error("invalid grammar trigger data")]
338 InvalidGrammarTriggerType,
339 #[error("Integer conversion error: {0}")]
341 IntConversionError(#[from] std::num::TryFromIntError),
342}
343
344#[derive(Debug, thiserror::Error)]
346pub enum ChatParseError {
347 #[error("{0}")]
349 NulError(#[from] NulError),
350 #[error("{0}")]
352 Utf8Error(#[from] FromUtf8Error),
353 #[error("null result from llama.cpp")]
355 NullResult,
356 #[error("ffi error {0}")]
358 FfiError(i32),
359}
360
361#[derive(Debug, thiserror::Error)]
363pub enum SamplerAcceptError {
364 #[error("C++ exception during sampler accept: {0}")]
366 CppException(String),
367
368 #[error("Invalid argument passed to sampler accept")]
370 InvalidArgument,
371}
372
373#[derive(Debug, Eq, PartialEq, thiserror::Error)]
375pub enum ModelParamsError {
376 #[error("No available slot in override vector")]
378 NoAvailableSlot,
379 #[error("Override slot is not empty")]
381 SlotNotEmpty,
382 #[error("Invalid character in key: byte {byte}, {reason}")]
384 InvalidCharacterInKey {
385 byte: u8,
387 reason: String,
389 },
390}
391
392#[derive(Debug, Eq, PartialEq, thiserror::Error)]
394pub enum TokenSamplingError {
395 #[error("No token was selected by the sampler")]
397 NoTokenSelected,
398}
399
400#[cfg(test)]
401mod tests {
402 use std::num::NonZeroI32;
403
404 use super::{DecodeError, EncodeError};
405
406 #[test]
407 fn decode_error_no_kv_cache_slot() {
408 let error = DecodeError::from(NonZeroI32::new(1).expect("1 is non-zero"));
409
410 assert_eq!(error, DecodeError::NoKvCacheSlot);
411 assert_eq!(error.to_string(), "Decode Error 1: NoKvCacheSlot");
412 }
413
414 #[test]
415 fn decode_error_n_tokens_zero() {
416 let error = DecodeError::from(NonZeroI32::new(-1).expect("-1 is non-zero"));
417
418 assert_eq!(error, DecodeError::NTokensZero);
419 assert_eq!(error.to_string(), "Decode Error -1: n_tokens == 0");
420 }
421
422 #[test]
423 fn decode_error_aborted() {
424 let error = DecodeError::from(NonZeroI32::new(2).expect("2 is non-zero"));
425
426 assert_eq!(error, DecodeError::Aborted);
427 assert_eq!(error.to_string(), "Decode Error 2: Aborted");
428 }
429
430 #[test]
431 fn decode_error_unknown() {
432 let error = DecodeError::from(NonZeroI32::new(42).expect("42 is non-zero"));
433
434 assert_eq!(error, DecodeError::Unknown(42));
435 assert_eq!(error.to_string(), "Decode Error 42: unknown");
436 }
437
438 #[test]
439 fn encode_error_no_kv_cache_slot() {
440 let error = EncodeError::from(NonZeroI32::new(1).expect("1 is non-zero"));
441
442 assert_eq!(error, EncodeError::NoKvCacheSlot);
443 assert_eq!(error.to_string(), "Encode Error 1: NoKvCacheSlot");
444 }
445
446 #[test]
447 fn encode_error_n_tokens_zero() {
448 let error = EncodeError::from(NonZeroI32::new(-1).expect("-1 is non-zero"));
449
450 assert_eq!(error, EncodeError::NTokensZero);
451 assert_eq!(error.to_string(), "Encode Error -1: n_tokens == 0");
452 }
453
454 #[test]
455 fn encode_error_unknown() {
456 let error = EncodeError::from(NonZeroI32::new(99).expect("99 is non-zero"));
457
458 assert_eq!(error, EncodeError::Unknown(99));
459 assert_eq!(error.to_string(), "Encode Error 99: unknown");
460 }
461}