1use std::path::PathBuf;
2
3use crate::model::TaskState;
4
5pub type Result<T, E = Error> = std::result::Result<T, E>;
6
7#[derive(Debug, thiserror::Error)]
8pub enum Error {
9 #[error("database error: {0}")]
10 Sqlite(#[from] rusqlite::Error),
11
12 #[error(
13 "this database is at schema version {version}, but this build of voro knows only {known} \
14 migration(s) — a newer build migrated it, and this one cannot read it safely. {remedy}"
15 )]
16 SchemaAhead {
17 version: usize,
18 known: usize,
19 remedy: String,
20 },
21
22 #[error(
23 "{} is protected and has {pending} pending migration(s) (schema {version} -> {known}); \
24 the operator's store never migrates as a side effect of being opened. The operator \
25 applies them by launching `voro` at a terminal, which asks first, or with \
26 `voro migrate`. If you are an agent or a script seeing this, stop and tell the \
27 operator; `voro migrate --yes` consents on their behalf and is recorded in the \
28 migration journal. A snapshot is written to backups/ beside the store before anything \
29 is applied.",
30 path.display()
31 )]
32 MigrationsPending {
33 path: PathBuf,
34 pending: usize,
35 version: usize,
36 known: usize,
37 },
38
39 #[error(
40 "this database's migration {idx} differs from the one this build carries: it was applied \
41 {applied_at} by {applied_by}. The version numbers agree, so nothing else will catch \
42 this — and since the two migrations are not the same text, this build cannot assume the \
43 schema it is about to query. {remedy}"
44 )]
45 SchemaDiverged {
46 idx: usize,
47 applied_at: String,
48 applied_by: String,
49 remedy: String,
50 },
51
52 #[error("task {0} not found")]
53 TaskNotFound(i64),
54
55 #[error("project {0} not found")]
56 ProjectNotFound(i64),
57
58 #[error(
59 "project {id} has {count} task(s) and cannot be deleted — set its weight to 0 to park \
60 it, or `voro project archive` to retire it; both keep its history"
61 )]
62 ProjectHasTasks { id: i64, count: i64 },
63
64 #[error("project '{name}' is archived — `voro project unarchive {name}` first")]
65 ProjectArchived { name: String },
66
67 #[error("no repo named '{name}' in project '{project}'; its repos: {known}")]
68 RepoNotFound {
69 project: String,
70 name: String,
71 known: String,
72 },
73
74 #[error("repo {0} not found")]
75 RepoIdNotFound(i64),
76
77 #[error("document {0} not found — `voro doc list` shows the registered ones")]
78 DocNotFound(i64),
79
80 #[error(
81 "repo '{name}' is the only repo in project '{project}' — a project always has a \
82 checkout, so add another repo before removing this one"
83 )]
84 LastRepo { project: String, name: String },
85
86 #[error(
87 "repo '{name}' is the default repo of project '{project}' — `voro repo default \
88 {project} <other>` first, so tasks without a repo still resolve"
89 )]
90 DefaultRepo { project: String, name: String },
91
92 #[error(
93 "repo '{name}' is used by {count} task(s) — re-point them with `voro set <task-id> \
94 --repo <other>` before removing it"
95 )]
96 RepoInUse { name: String, count: i64 },
97
98 #[error("session {0} not found")]
99 SessionNotFound(i64),
100
101 #[error("cannot {action} a task in state '{from}'")]
102 InvalidTransition { from: TaskState, action: String },
103
104 #[error("task {id} is human-only: {reason}")]
105 HumanTask { id: i64, reason: String },
106
107 #[error("blocks dependency would create a cycle: {0}")]
108 DependencyCycle(String),
109
110 #[error(
111 "no default agent: none of the built-in agents ({probed}) were found on PATH; \
112 install one, or set `default_agent` in {} to a configured agent",
113 path.display()
114 )]
115 NoDefaultAgent { probed: String, path: PathBuf },
116
117 #[error("invalid agents config at {}: {message}", path.display())]
118 AgentConfigInvalid { path: PathBuf, message: String },
119
120 #[error(
121 "no viewer set up — run `voro viewer add <name> '<cmd>'`, e.g. \
122 `voro viewer add zed 'zed {{path}}'`; none of the built-in {probed} are on PATH"
123 )]
124 NoViewer { probed: String },
125
126 #[error(
127 "no viewer named '{name}' — run `voro viewer add {name} '<cmd>'` to define it in {}; \
128 available viewers: {known}",
129 path.display()
130 )]
131 UnknownViewer {
132 name: String,
133 known: String,
134 path: PathBuf,
135 },
136
137 #[error("no agent named '{name}' ({origin}) in {}; defined agents: {known}", path.display())]
138 UnknownAgent {
139 name: String,
140 origin: &'static str,
141 path: PathBuf,
142 known: String,
143 },
144
145 #[error("{0}")]
146 Invalid(String),
147}