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 initialization failed: {0}")]
179 NullGrammar(String),
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
196#[derive(Debug, Eq, PartialEq, thiserror::Error)]
198pub enum SampleError {
199 #[error("C++ exception during sampling: {0}")]
201 CppException(String),
202
203 #[error("Invalid argument passed to sampler")]
205 InvalidArgument,
206}
207
208impl From<NonZeroI32> for DecodeError {
210 fn from(value: NonZeroI32) -> Self {
211 match value.get() {
212 1 => Self::NoKvCacheSlot,
213 -1 => Self::NTokensZero,
214 error_code => Self::Unknown(error_code),
215 }
216 }
217}
218
219impl From<NonZeroI32> for EncodeError {
221 fn from(value: NonZeroI32) -> Self {
222 match value.get() {
223 1 => Self::NoKvCacheSlot,
224 -1 => Self::NTokensZero,
225 error_code => Self::Unknown(error_code),
226 }
227 }
228}
229
230#[derive(Debug, Eq, PartialEq, thiserror::Error)]
232pub enum LlamaModelLoadError {
233 #[error("null byte in string {0}")]
235 NullError(#[from] NulError),
236 #[error("null result from llama cpp")]
238 NullResult,
239 #[error("failed to convert path {0} to str")]
241 PathToStrError(PathBuf),
242 #[error("model file not found: {0}")]
244 FileNotFound(PathBuf),
245}
246
247#[derive(Debug, Eq, PartialEq, thiserror::Error)]
249pub enum LlamaLoraAdapterInitError {
250 #[error("null byte in string {0}")]
252 NullError(#[from] NulError),
253 #[error("null result from llama cpp")]
255 NullResult,
256 #[error("failed to convert path {0} to str")]
258 PathToStrError(PathBuf),
259 #[error("adapter file not found: {0}")]
261 FileNotFound(PathBuf),
262}
263
264#[derive(Debug, Eq, PartialEq, thiserror::Error)]
266pub enum LlamaLoraAdapterSetError {
267 #[error("error code from llama cpp")]
269 ErrorResult(i32),
270}
271
272#[derive(Debug, Eq, PartialEq, thiserror::Error)]
274pub enum LlamaLoraAdapterRemoveError {
275 #[error("error code from llama cpp")]
277 ErrorResult(i32),
278}
279
280#[derive(Debug, thiserror::Error, Clone)]
282#[non_exhaustive]
283pub enum TokenToStringError {
284 #[error("Unknown Token Type")]
286 UnknownTokenType,
287 #[error("Insufficient Buffer Space {0}")]
289 InsufficientBufferSpace(c_int),
290 #[error("FromUtf8Error {0}")]
292 FromUtf8Error(#[from] FromUtf8Error),
293 #[error("Integer conversion error: {0}")]
295 IntConversionError(#[from] std::num::TryFromIntError),
296}
297
298#[derive(Debug, thiserror::Error)]
300pub enum StringToTokenError {
301 #[error("{0}")]
303 NulError(#[from] NulError),
304 #[error("{0}")]
305 CIntConversionError(#[from] std::num::TryFromIntError),
307}
308
309#[derive(Debug, thiserror::Error)]
311pub enum NewLlamaChatMessageError {
312 #[error("{0}")]
314 NulError(#[from] NulError),
315}
316
317#[derive(Debug, thiserror::Error)]
319pub enum ApplyChatTemplateError {
320 #[error("{0}")]
322 NulError(#[from] NulError),
323 #[error("{0}")]
325 FromUtf8Error(#[from] FromUtf8Error),
326 #[error("null result from llama.cpp")]
328 NullResult,
329 #[error("ffi error {0}")]
331 FfiError(i32),
332 #[error("invalid grammar trigger data")]
334 InvalidGrammarTriggerType,
335 #[error("Integer conversion error: {0}")]
337 IntConversionError(#[from] std::num::TryFromIntError),
338}
339
340#[derive(Debug, thiserror::Error)]
342pub enum ChatParseError {
343 #[error("{0}")]
345 NulError(#[from] NulError),
346 #[error("{0}")]
348 Utf8Error(#[from] FromUtf8Error),
349 #[error("null result from llama.cpp")]
351 NullResult,
352 #[error("ffi error {0}")]
354 FfiError(i32),
355}
356
357#[derive(Debug, thiserror::Error)]
359pub enum SamplerAcceptError {
360 #[error("C++ exception during sampler accept: {0}")]
362 CppException(String),
363
364 #[error("Invalid argument passed to sampler accept")]
366 InvalidArgument,
367}
368
369#[derive(Debug, Eq, PartialEq, thiserror::Error)]
371pub enum ModelParamsError {
372 #[error("No available slot in override vector")]
374 NoAvailableSlot,
375 #[error("Override slot is not empty")]
377 SlotNotEmpty,
378 #[error("Invalid character in key: byte {byte}, {reason}")]
380 InvalidCharacterInKey {
381 byte: u8,
383 reason: String,
385 },
386}
387
388#[derive(Debug, Eq, PartialEq, thiserror::Error)]
390pub enum TokenSamplingError {
391 #[error("No token was selected by the sampler")]
393 NoTokenSelected,
394}
395
396#[cfg(test)]
397mod tests {
398 use std::num::NonZeroI32;
399
400 use super::{DecodeError, EncodeError};
401
402 #[test]
403 fn decode_error_no_kv_cache_slot() {
404 let error = DecodeError::from(NonZeroI32::new(1).expect("1 is non-zero"));
405
406 assert_eq!(error, DecodeError::NoKvCacheSlot);
407 assert_eq!(error.to_string(), "Decode Error 1: NoKvCacheSlot");
408 }
409
410 #[test]
411 fn decode_error_n_tokens_zero() {
412 let error = DecodeError::from(NonZeroI32::new(-1).expect("-1 is non-zero"));
413
414 assert_eq!(error, DecodeError::NTokensZero);
415 assert_eq!(error.to_string(), "Decode Error -1: n_tokens == 0");
416 }
417
418 #[test]
419 fn decode_error_unknown() {
420 let error = DecodeError::from(NonZeroI32::new(42).expect("42 is non-zero"));
421
422 assert_eq!(error, DecodeError::Unknown(42));
423 assert_eq!(error.to_string(), "Decode Error 42: unknown");
424 }
425
426 #[test]
427 fn encode_error_no_kv_cache_slot() {
428 let error = EncodeError::from(NonZeroI32::new(1).expect("1 is non-zero"));
429
430 assert_eq!(error, EncodeError::NoKvCacheSlot);
431 assert_eq!(error.to_string(), "Encode Error 1: NoKvCacheSlot");
432 }
433
434 #[test]
435 fn encode_error_n_tokens_zero() {
436 let error = EncodeError::from(NonZeroI32::new(-1).expect("-1 is non-zero"));
437
438 assert_eq!(error, EncodeError::NTokensZero);
439 assert_eq!(error.to_string(), "Encode Error -1: n_tokens == 0");
440 }
441
442 #[test]
443 fn encode_error_unknown() {
444 let error = EncodeError::from(NonZeroI32::new(99).expect("99 is non-zero"));
445
446 assert_eq!(error, EncodeError::Unknown(99));
447 assert_eq!(error.to_string(), "Encode Error 99: unknown");
448 }
449}