Skip to main content

oxibonsai_core/
error.rs

1//! Error types for OxiBonsai core operations.
2
3use thiserror::Error;
4
5/// Result type alias for OxiBonsai core operations.
6pub type BonsaiResult<T> = Result<T, BonsaiError>;
7
8/// Errors that can occur during GGUF parsing, tensor loading, and configuration.
9#[derive(Error, Debug)]
10pub enum BonsaiError {
11    /// Invalid GGUF magic number in file header.
12    #[error("invalid GGUF magic number: expected 0x46554747, got 0x{magic:08X}")]
13    InvalidMagic { magic: u32 },
14
15    /// Unsupported GGUF format version.
16    #[error("unsupported GGUF version: {version} (supported: 2, 3)")]
17    UnsupportedVersion { version: u32 },
18
19    /// Invalid or missing metadata entry.
20    #[error("invalid metadata for key '{key}': {reason}")]
21    InvalidMetadata { key: String, reason: String },
22
23    /// A required tensor was not found in the model file.
24    #[error("tensor not found: '{name}'")]
25    TensorNotFound { name: String },
26
27    /// Unsupported quantization type encountered.
28    #[error("unsupported quantization type id {type_id}: known execution types are Q1_0_g128=41, TQ2_0_g128=42, TQ2_0=35")]
29    UnsupportedQuantType { type_id: u32 },
30
31    /// Memory mapping failed.
32    #[error("memory mapping failed: {0}")]
33    MmapError(#[from] std::io::Error),
34
35    /// Unexpected end of file during parsing.
36    #[error("unexpected end of file at offset {offset}")]
37    UnexpectedEof { offset: u64 },
38
39    /// Data alignment error.
40    #[error("alignment error: expected {expected}-byte alignment at offset {offset}")]
41    AlignmentError { expected: usize, offset: u64 },
42
43    /// Invalid string encoding in GGUF data.
44    #[error("invalid UTF-8 string at offset {offset}")]
45    InvalidString { offset: u64 },
46
47    /// A required configuration key is missing from model metadata.
48    #[error("missing config key '{key}' in model metadata")]
49    MissingConfigKey { key: String },
50
51    /// Dimension mismatch between expected and actual tensor shape.
52    #[error("tensor '{name}' shape mismatch: expected {expected:?}, got {actual:?}")]
53    ShapeMismatch {
54        name: String,
55        expected: Vec<u64>,
56        actual: Vec<u64>,
57    },
58
59    /// Block size validation failed.
60    #[error("invalid Q1_0_g128 block: expected 18 bytes, got {actual}")]
61    InvalidBlockSize { actual: usize },
62
63    /// K-quant quantization or dequantization error.
64    #[error("k-quant error: {reason}")]
65    KQuantError { reason: String },
66}
67
68impl BonsaiError {
69    /// Return a short, stable error code string for monitoring and alerting.
70    pub fn error_code(&self) -> &str {
71        match self {
72            Self::InvalidMagic { .. } => "INVALID_MAGIC",
73            Self::UnsupportedVersion { .. } => "UNSUPPORTED_VERSION",
74            Self::InvalidMetadata { .. } => "INVALID_METADATA",
75            Self::TensorNotFound { .. } => "TENSOR_NOT_FOUND",
76            Self::UnsupportedQuantType { .. } => "UNSUPPORTED_QUANT_TYPE",
77            Self::MmapError(_) => "MMAP_ERROR",
78            Self::UnexpectedEof { .. } => "UNEXPECTED_EOF",
79            Self::AlignmentError { .. } => "ALIGNMENT_ERROR",
80            Self::InvalidString { .. } => "INVALID_STRING",
81            Self::MissingConfigKey { .. } => "MISSING_CONFIG_KEY",
82            Self::ShapeMismatch { .. } => "SHAPE_MISMATCH",
83            Self::InvalidBlockSize { .. } => "INVALID_BLOCK_SIZE",
84            Self::KQuantError { .. } => "K_QUANT_ERROR",
85        }
86    }
87
88    /// Whether this error is potentially recoverable by retrying.
89    pub fn is_retryable(&self) -> bool {
90        matches!(self, Self::MmapError(_))
91    }
92}