Skip to main content

synd_runtime/
error.rs

1use std::{path::PathBuf, process::ExitStatus};
2
3use synd_protocol::CapabilitySet;
4
5use thiserror::Error;
6
7use crate::DaemonLaunchInfo;
8
9pub type Result<T> = std::result::Result<T, Error>;
10
11#[derive(Debug, Error)]
12pub enum Error {
13    #[error(transparent)]
14    Io(#[from] std::io::Error),
15
16    #[error(transparent)]
17    RegistryDb(#[from] synd_registry::RegistryDbError),
18
19    #[error(transparent)]
20    Migration(#[from] synd_persistence::sqlite::MigrationError),
21
22    #[error(transparent)]
23    Api(Box<synd_client::SyndApiError>),
24
25    #[error(transparent)]
26    RuntimeApi(Box<synd_api::Error>),
27
28    #[error(transparent)]
29    Json(#[from] serde_json::Error),
30
31    #[error("{context} endpoint unavailable: {}", endpoint.display())]
32    EndpointUnavailable {
33        context: &'static str,
34        endpoint: PathBuf,
35    },
36
37    #[error("{context} transport unsupported")]
38    UnsupportedTransport { context: &'static str },
39
40    #[error(
41        "runtime daemon at {} is missing required session capabilities: {missing_capabilities}",
42        endpoint.display()
43    )]
44    MissingSessionCapabilities {
45        endpoint: PathBuf,
46        missing_capabilities: CapabilitySet,
47    },
48
49    #[error("refusing to remove non-socket runtime endpoint {}", path.display())]
50    NonSocketEndpoint { path: PathBuf },
51
52    #[error(
53        "daemon exited before endpoint became ready: {status}; daemon log: {}",
54        launch.log().display()
55    )]
56    DaemonExitedBeforeReady {
57        status: ExitStatus,
58        launch: DaemonLaunchInfo,
59    },
60
61    #[error(
62        "timed out waiting for launched daemon endpoint {} to become ready; daemon log: {}",
63        endpoint.display(),
64        launch.log().display()
65    )]
66    DaemonEndpointReadyTimeout {
67        endpoint: PathBuf,
68        launch: DaemonLaunchInfo,
69    },
70
71    #[error("timed out waiting for daemon endpoint {} to become ready", endpoint.display())]
72    EndpointReadyTimeout { endpoint: PathBuf },
73
74    #[error("timed out waiting for daemon endpoint {} to stop", endpoint.display())]
75    EndpointStopTimeout { endpoint: PathBuf },
76
77    #[error("daemon claim lock is already held at {}", path.display())]
78    DaemonClaimLockAlreadyHeld { path: PathBuf },
79
80    #[error("refusing force shutdown: {reason}")]
81    ForceShutdownRefused { reason: String },
82
83    #[error("timed out force stopping daemon process {pid}")]
84    ForceShutdownTimeout { pid: u32 },
85
86    #[error("runtime daemon is incompatible at {}; {suggestion}", endpoint.display())]
87    IncompatibleRuntimeDaemon {
88        endpoint: PathBuf,
89        suggestion: String,
90    },
91
92    #[error("failed to stop incompatible runtime daemon at {}; {suggestion}", endpoint.display())]
93    IncompatibleRuntimeDaemonShutdown {
94        endpoint: PathBuf,
95        suggestion: String,
96        #[source]
97        source: Box<synd_client::SyndApiError>,
98    },
99
100    #[error("timed out stopping incompatible runtime daemon at {}; {suggestion}", endpoint.display())]
101    IncompatibleRuntimeDaemonStopTimeout {
102        endpoint: PathBuf,
103        suggestion: String,
104    },
105}
106
107impl From<synd_client::SyndApiError> for Error {
108    fn from(source: synd_client::SyndApiError) -> Self {
109        Self::Api(Box::new(source))
110    }
111}
112
113impl From<synd_api::Error> for Error {
114    fn from(source: synd_api::Error) -> Self {
115        Self::RuntimeApi(Box::new(source))
116    }
117}