Skip to main content

dedup/
error.rs

1//! Error types for the dedup crate.
2//!
3//! Every error is actionable and tells you how to fix the problem.
4
5/// All errors that can occur during deduplication.
6#[derive(Debug, thiserror::Error)]
7#[non_exhaustive]
8pub enum Error {
9    /// Configuration was invalid.
10    #[error("invalid configuration: {reason}. Fix: {fix}")]
11    InvalidConfig {
12        /// What was wrong.
13        reason: String,
14        /// How to fix it.
15        fix: String,
16    },
17
18    /// A document was too large to process.
19    #[error("document too large: size={size}, max={max}. Fix: increase max_document_size in Config or filter large documents before deduplication.")]
20    DocumentTooLarge {
21        /// Actual document size.
22        size: usize,
23        /// Maximum allowed size.
24        max: usize,
25    },
26
27    /// A document was empty and cannot be processed.
28    #[error("empty document at index {index}. Fix: filter empty documents before deduplication.")]
29    EmptyDocument {
30        /// Index of the empty document.
31        index: usize,
32    },
33
34    /// Internal error during hashing.
35    #[error("hashing failed: {reason}. Fix: check for integer overflow or memory exhaustion.")]
36    HashingFailed {
37        /// What went wrong.
38        reason: String,
39    },
40
41    /// Memory limit exceeded.
42    #[error("memory limit exceeded: {usage_bytes} bytes. Fix: increase memory_limit_in_mb in Config or reduce num_bands.")]
43    MemoryLimitExceeded {
44        /// Current memory usage in bytes.
45        usage_bytes: u64,
46    },
47
48    /// IO error during processing.
49    #[error("io error: {0}. Fix: check file permissions and disk space.")]
50    Io(#[from] std::io::Error),
51}
52
53/// Convenience result type.
54pub type Result<T> = std::result::Result<T, Error>;
55
56#[cfg(test)]
57mod tests {
58    use super::*;
59
60    #[test]
61    fn error_display_includes_fix() {
62        let err = Error::InvalidConfig {
63            reason: "num_bands must divide signature_size".to_string(),
64            fix: "use a signature_size divisible by num_bands".to_string(),
65        };
66        let msg = err.to_string();
67        assert!(msg.contains("Fix:"));
68        assert!(msg.contains("signature_size"));
69    }
70
71    #[test]
72    fn document_too_large_error_includes_size() {
73        let err = Error::DocumentTooLarge {
74            size: 1000000,
75            max: 100000,
76        };
77        let msg = err.to_string();
78        assert!(msg.contains("1000000"));
79        assert!(msg.contains("100000"));
80    }
81}