1use std::io;
2use std::path::PathBuf;
3
4use thiserror::Error;
5
6#[derive(Debug, Error)]
7pub enum SboxError {
8 #[error("config file not found: {}", .0.display())]
9 ConfigNotFound(PathBuf),
10
11 #[error("failed to read config {}: {source}", path.display())]
12 ConfigRead {
13 path: PathBuf,
14 #[source]
15 source: io::Error,
16 },
17
18 #[error("failed to parse config {}: {source}", path.display())]
19 ConfigParse {
20 path: PathBuf,
21 #[source]
22 source: serde_yaml::Error,
23 },
24
25 #[error("invalid config:\n{message}")]
26 ConfigValidation { message: String },
27
28 #[error("unknown profile `{name}`")]
29 UnknownProfile { name: String },
30
31 #[error("unknown preset `{name}`")]
32 UnknownPreset { name: String },
33
34 #[error("no shell could be resolved")]
35 NoShellResolved,
36
37 #[error("refusing unsafe sandbox execution for `{command}`: {reason}")]
38 UnsafeExecutionPolicy { command: String, reason: String },
39
40 #[error("pre-run command `{pre_run}` failed before `{command}` with exit status `{status}`")]
41 PreRunFailed {
42 pre_run: String,
43 command: String,
44 status: u8,
45 },
46
47 #[error("image signature verification is unavailable for `{image}`: {reason}")]
48 SignatureVerificationUnavailable { image: String, reason: String },
49
50 #[error(
51 "image signature verification failed for `{image}` using policy {}: {reason}",
52 policy.display()
53 )]
54 SignatureVerificationFailed {
55 image: String,
56 policy: PathBuf,
57 reason: String,
58 },
59
60 #[error("refusing to overwrite existing config {}", path.display())]
61 InitConfigExists { path: PathBuf },
62
63 #[error("failed to write generated config {}: {source}", path.display())]
64 InitWrite {
65 path: PathBuf,
66 #[source]
67 source: io::Error,
68 },
69
70 #[error(
71 "failed to resolve a profile for command `{command}`; define a `default` profile or pass `--profile`"
72 )]
73 ProfileResolutionFailed { command: String },
74
75 #[error("failed to start command `{program}`: {source}")]
76 CommandSpawn {
77 program: String,
78 #[source]
79 source: io::Error,
80 },
81
82 #[error("backend `{backend}` is unavailable: {source}")]
83 BackendUnavailable {
84 backend: String,
85 #[source]
86 source: io::Error,
87 },
88
89 #[error("backend `{backend}` command failed: `{command}` exited with status `{status}`")]
90 BackendCommandFailed {
91 backend: String,
92 command: String,
93 status: i32,
94 },
95
96 #[error(
97 "sandbox execution is not implemented yet for profile `{profile}` with backend `{backend}`"
98 )]
99 SandboxExecutionNotImplemented { profile: String, backend: String },
100
101 #[error("unsupported mount type `{mount_type}`")]
102 UnsupportedMountType { mount_type: String },
103
104 #[error("host path for {kind} `{name}` does not exist or is not accessible: {}", path.display())]
105 HostPathNotFound {
106 kind: &'static str,
107 name: String,
108 path: PathBuf,
109 },
110
111 #[error(
112 "secret `{name}` uses unsupported source `{secret_source}`; only host path sources are implemented"
113 )]
114 UnsupportedSecretSource { name: String, secret_source: String },
115
116 #[error("reusable sandbox sessions are not implemented yet for profile `{profile}`")]
117 ReusableSandboxSessionsNotImplemented { profile: String },
118
119 #[error("failed to determine current directory: {source}")]
120 CurrentDirectory {
121 #[source]
122 source: io::Error,
123 },
124
125 #[error("failed to initialize logging: {source}")]
126 LoggingInit {
127 #[source]
128 source: Box<dyn std::error::Error + Send + Sync>,
129 },
130}