Skip to main content

uqa_analysis/
error.rs

1//
2// Unified Query Algebra
3//
4// Copyright (c) 2023-2026 Cognica, Inc.
5//
6
7//! Errors produced while executing an analysis pipeline.
8
9use regex::Error as RegexError;
10
11use crate::token_filter::SynonymFileError;
12
13/// An invalid analyzer is an execution error, never an empty token stream.
14#[derive(Debug, thiserror::Error)]
15pub enum AnalysisError {
16    #[error(transparent)]
17    Memory(#[from] uqa_core::memory::MemoryError),
18    #[error("this pipeline has no normalization plan")]
19    NormalizationUnavailable,
20    #[error("invalid analyzer descriptor: {0}")]
21    Descriptor(&'static str),
22    #[error("analyzer {component} revision {actual} is unavailable; expected {expected}")]
23    DescriptorRevision {
24        component: &'static str,
25        expected: u32,
26        actual: u32,
27    },
28    #[error("analyzer fingerprint mismatch: expected {expected}, received {actual}")]
29    DescriptorFingerprint {
30        expected: crate::AnalyzerFingerprint,
31        actual: crate::AnalyzerFingerprint,
32    },
33    #[error("analysis needs {required} {resource}, exceeding limit {limit}")]
34    ResourceLimit {
35        resource: &'static str,
36        required: usize,
37        limit: usize,
38    },
39    #[error("invalid analyzer JSON: {0}")]
40    Json(#[from] serde_json::Error),
41    #[error("analysis cancelled")]
42    Cancelled,
43    #[error("token contains unpaired UTF-16 surrogate {unit:#06x}; use its lossless term units")]
44    UnpairedTokenSurrogate { unit: u16 },
45    #[error("analysis expected {expected_utf16} UTF-16 input units, but received {actual_utf16}")]
46    MismatchedAnalysisInput {
47        expected_utf16: usize,
48        actual_utf16: usize,
49    },
50    #[cfg(feature = "nori")]
51    #[error(transparent)]
52    Dictionary(#[from] crate::nori::DictionaryError),
53    #[cfg(feature = "kuromoji")]
54    #[error(transparent)]
55    KuromojiDictionary(#[from] crate::kuromoji::DictionaryError),
56    #[error("{coordinate} offset {offset} is not a Unicode scalar boundary within text of length {length}")]
57    InvalidTextOffset {
58        coordinate: &'static str,
59        offset: usize,
60        length: usize,
61    },
62    #[error("text span start {start} exceeds its end {end}")]
63    InvalidTextSpan { start: usize, end: usize },
64    #[error("character-filter edits overlap or are out of order")]
65    OverlappingTextEdits,
66    #[error("highlighting requires original source offsets for every matching token")]
67    MissingTokenOffsets,
68    #[error("token graphs require a positive first increment and positive position lengths")]
69    InvalidTokenPosition,
70    #[error("token position exceeds the u32 position format")]
71    TokenPositionOverflow,
72    #[error("invalid {component} regular expression `{pattern}`: {source}")]
73    InvalidRegex {
74        component: &'static str,
75        pattern: String,
76        #[source]
77        source: RegexError,
78    },
79    #[error("failed to initialize built-in {component} regular expression: {message}")]
80    BuiltInRegex {
81        component: &'static str,
82        message: String,
83    },
84    #[error(
85        "invalid {component} gram bounds: min_gram must be at least 1 and max_gram must be greater than or equal to min_gram (got {min_gram}..={max_gram})"
86    )]
87    InvalidGramBounds {
88        component: &'static str,
89        min_gram: usize,
90        max_gram: usize,
91    },
92    #[error(transparent)]
93    SynonymFile(#[from] SynonymFileError),
94}
95
96pub type AnalysisResult<T> = std::result::Result<T, AnalysisError>;