1use std::path::PathBuf;
2
3use miette::Diagnostic;
4
5#[derive(Debug, thiserror::Error, Diagnostic)]
19pub enum ArgusError {
20 #[error("IO error: {0}")]
22 #[diagnostic(code(argus::io), help("Check file permissions and paths"))]
23 Io(#[from] std::io::Error),
24
25 #[error("Configuration error: {0}")]
27 #[diagnostic(
28 code(argus::config),
29 help("Run `argus init` to create a default config, or check .argus.toml syntax")
30 )]
31 Config(String),
32
33 #[error("Git error: {0}")]
35 #[diagnostic(code(argus::git), help("Make sure you're inside a git repository"))]
36 Git(String),
37
38 #[error("GitHub API error: {0}")]
40 #[diagnostic(
41 code(argus::github),
42 help("Check your GITHUB_TOKEN permissions and network connection")
43 )]
44 GitHub(String),
45
46 #[error("Parse error: {0}")]
48 #[diagnostic(
49 code(argus::parse),
50 help("Check that the file is valid source code in a supported language")
51 )]
52 Parse(String),
53
54 #[error("LLM error: {0}")]
56 #[diagnostic(code(argus::llm), help("Check your API key and provider config in .argus.toml. Run `argus doctor` to diagnose."))]
57 Llm(String),
58
59 #[error("Serialization error: {0}")]
61 #[diagnostic(code(argus::serde))]
62 Serialization(#[from] serde_json::Error),
63
64 #[error("TOML parse error: {0}")]
66 #[diagnostic(
67 code(argus::toml),
68 help("Check .argus.toml syntax — run `argus init` to generate a fresh one")
69 )]
70 Toml(#[from] toml::de::Error),
71
72 #[error("File not found: {}", .0.display())]
74 #[diagnostic(
75 code(argus::file_not_found),
76 help("Check the path exists and is readable")
77 )]
78 FileNotFound(PathBuf),
79
80 #[error("Embedding error: {0}")]
82 #[diagnostic(
83 code(argus::embedding),
84 help("Check your embedding provider API key. Run `argus doctor` to diagnose.")
85 )]
86 Embedding(String),
87
88 #[error("Database error: {0}")]
90 #[diagnostic(
91 code(argus::database),
92 help("Try deleting .argus/index.db and re-indexing")
93 )]
94 Database(String),
95}
96
97#[cfg(test)]
98mod tests {
99 use super::*;
100
101 #[test]
102 fn io_error_converts() {
103 let io_err = std::io::Error::new(std::io::ErrorKind::NotFound, "gone");
104 let err: ArgusError = io_err.into();
105 assert!(err.to_string().contains("gone"));
106 }
107
108 #[test]
109 fn config_error_displays_message() {
110 let err = ArgusError::Config("bad value".into());
111 assert_eq!(err.to_string(), "Configuration error: bad value");
112 }
113
114 #[test]
115 fn file_not_found_shows_path() {
116 let err = ArgusError::FileNotFound(PathBuf::from("/tmp/missing.rs"));
117 assert!(err.to_string().contains("/tmp/missing.rs"));
118 }
119}