Skip to main content

vibe_graph_ops/
error.rs

1//! Error types for the operations layer.
2
3use std::path::PathBuf;
4use thiserror::Error;
5
6/// Result type for operations.
7pub type OpsResult<T> = Result<T, OpsError>;
8
9/// Errors that can occur during operations.
10#[derive(Debug, Error)]
11pub enum OpsError {
12    /// Workspace not found at the specified path.
13    #[error("No workspace found at {path}")]
14    WorkspaceNotFound { path: PathBuf },
15
16    /// The .self store doesn't exist (need to sync first).
17    #[error("No .self folder found at {path}. Run sync first.")]
18    StoreNotFound { path: PathBuf },
19
20    /// Project data not found in the store.
21    #[error("No project data found in .self store")]
22    ProjectNotFound,
23
24    /// Graph data not found in the store.
25    #[error("No graph data found in .self store")]
26    GraphNotFound,
27
28    /// GitHub credentials not configured.
29    #[error("GitHub credentials not configured. Set GITHUB_USERNAME and GITHUB_TOKEN or use `vg config set`")]
30    GitHubNotConfigured,
31
32    /// Failed to clone a repository.
33    #[error("Failed to clone repository {repo}: {message}")]
34    CloneFailed { repo: String, message: String },
35
36    /// Failed to fetch from GitHub API.
37    #[error("GitHub API error for {resource}: {message}")]
38    GitHubApiError { resource: String, message: String },
39
40    /// IO error during file operations.
41    #[error("IO error: {0}")]
42    Io(#[from] std::io::Error),
43
44    /// JSON serialization/deserialization error.
45    #[error("JSON error: {0}")]
46    Json(#[from] serde_json::Error),
47
48    /// Git operation error.
49    #[error("Git error: {0}")]
50    Git(#[from] git2::Error),
51
52    /// Path resolution error.
53    #[error("Failed to resolve path {path}: {message}")]
54    PathResolution { path: PathBuf, message: String },
55
56    /// Configuration error.
57    #[error("Configuration error: {0}")]
58    Config(String),
59
60    /// Generic error with context.
61    #[error("{context}: {message}")]
62    WithContext { context: String, message: String },
63}
64
65impl OpsError {
66    /// Create a new error with additional context.
67    pub fn with_context(context: impl Into<String>, message: impl Into<String>) -> Self {
68        Self::WithContext {
69            context: context.into(),
70            message: message.into(),
71        }
72    }
73
74    /// Create a path resolution error.
75    pub fn path_resolution(path: impl Into<PathBuf>, message: impl Into<String>) -> Self {
76        Self::PathResolution {
77            path: path.into(),
78            message: message.into(),
79        }
80    }
81}
82
83impl From<anyhow::Error> for OpsError {
84    fn from(err: anyhow::Error) -> Self {
85        OpsError::WithContext {
86            context: "Operation failed".to_string(),
87            message: err.to_string(),
88        }
89    }
90}