use std::fmt;
#[derive(Debug, Clone)]
pub enum RagrigError {
ContextSizeExceeded {
current: usize,
max: usize,
},
EmbedModelNotFound {
model: String,
},
StoreCorrupt {
path: String,
},
NoDocumentsFound {
folder: String,
},
}
impl fmt::Display for RagrigError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::ContextSizeExceeded { current, max } => {
write!(f, "prompt size {current} tokens exceeds model context window of {max} tokens")
}
Self::EmbedModelNotFound { model } => {
write!(f, "embedding model '{model}' not found — is it pulled? Try: ollama pull {model}")
}
Self::StoreCorrupt { path } => {
write!(f, "vector store at '{path}' is corrupt — delete it and re-index")
}
Self::NoDocumentsFound { folder } => {
write!(f, "no documents found in '{folder}' — add PDF, EPUB, or HTML files")
}
}
}
}
impl std::error::Error for RagrigError {}
impl RagrigError {
pub fn current_size(&self) -> usize {
match self {
Self::ContextSizeExceeded { current, .. } => *current,
_ => 0,
}
}
pub fn max_size(&self) -> usize {
match self {
Self::ContextSizeExceeded { max, .. } => *max,
_ => 0,
}
}
pub fn model_name(&self) -> &str {
match self {
Self::EmbedModelNotFound { model } => model,
_ => "",
}
}
pub fn store_path(&self) -> &str {
match self {
Self::StoreCorrupt { path } => path,
_ => "",
}
}
pub fn folder(&self) -> &str {
match self {
Self::NoDocumentsFound { folder } => folder,
_ => "",
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn context_size_exceeded_accessors() {
let err = RagrigError::ContextSizeExceeded { current: 5000, max: 4096 };
assert_eq!(err.current_size(), 5000);
assert_eq!(err.max_size(), 4096);
}
#[test]
fn context_size_exceeded_display() {
let err = RagrigError::ContextSizeExceeded { current: 5000, max: 4096 };
let msg = err.to_string();
assert!(msg.contains("5000"));
assert!(msg.contains("4096"));
}
#[test]
fn embed_model_not_found_display() {
let err = RagrigError::EmbedModelNotFound { model: "nomic-embed-text".into() };
let msg = err.to_string();
assert!(msg.contains("nomic-embed-text"));
assert!(msg.contains("ollama pull"));
}
#[test]
fn store_corrupt_display() {
let err = RagrigError::StoreCorrupt { path: "/tmp/store".into() };
let msg = err.to_string();
assert!(msg.contains("/tmp/store"));
assert!(msg.contains("corrupt"));
}
#[test]
fn no_documents_found_display() {
let err = RagrigError::NoDocumentsFound { folder: "/docs".into() };
let msg = err.to_string();
assert!(msg.contains("/docs"));
assert!(msg.contains("no documents"));
}
#[test]
fn downcast_from_anyhow() {
let err = anyhow::Error::new(RagrigError::ContextSizeExceeded { current: 100, max: 50 });
let downcast = err.downcast_ref::<RagrigError>();
assert!(downcast.is_some());
assert_eq!(downcast.unwrap().current_size(), 100);
}
#[test]
fn accessors_return_default_on_wrong_variant() {
let err = RagrigError::NoDocumentsFound { folder: "x".into() };
assert_eq!(err.current_size(), 0);
assert_eq!(err.max_size(), 0);
assert_eq!(err.store_path(), "");
assert_eq!(err.model_name(), "");
}
}