Skip to main content

leviath_runtime/embed/
error.rs

1//! Errors from building or driving an embedded world.
2
3/// Why an [`AgentWorld`](super::AgentWorld) could not be built or a request to
4/// it could not be served.
5#[derive(Debug, Clone, PartialEq, Eq)]
6#[non_exhaustive]
7pub enum EmbedError {
8    /// The builder was given no providers: no credentials and no custom
9    /// provider registrations. A world with nothing to infer against can only
10    /// error, so this fails at build time instead.
11    NoProviders,
12    /// No Tokio runtime was found. `build()` must run inside a Tokio runtime
13    /// (or be given a handle via
14    /// [`runtime`](super::AgentWorldBuilder::runtime)).
15    NoRuntime,
16    /// The blueprint could not be loaded, parsed, or validated.
17    Blueprint(String),
18    /// The spawn was rejected (bad workdir, unresolvable seeds, and so on).
19    Spawn(String),
20    /// A configured provider's outbound HTTPS client could not be built, so
21    /// that provider could never reach its API. In practice the machine's root
22    /// certificate store could not be read; it is unrelated to any TLS
23    /// certificate the host itself serves.
24    ProviderClient(String),
25    /// The world's serve loop is gone (already shut down), so the request
26    /// could not be delivered or answered.
27    ChannelClosed,
28}
29
30impl std::fmt::Display for EmbedError {
31    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
32        match self {
33            EmbedError::NoProviders => {
34                write!(f, "no providers configured: add credentials or a provider")
35            }
36            EmbedError::NoRuntime => {
37                write!(f, "no tokio runtime: build inside one or pass a handle")
38            }
39            EmbedError::Blueprint(msg) => write!(f, "blueprint error: {msg}"),
40            EmbedError::Spawn(msg) => write!(f, "spawn error: {msg}"),
41            EmbedError::ProviderClient(msg) => {
42                write!(f, "provider HTTPS client error: {msg}")
43            }
44            EmbedError::ChannelClosed => write!(f, "the world has shut down"),
45        }
46    }
47}
48
49impl std::error::Error for EmbedError {}
50
51#[cfg(test)]
52mod tests {
53    use super::*;
54
55    #[test]
56    fn display_covers_every_variant() {
57        let cases = [
58            (EmbedError::NoProviders, "no providers"),
59            (EmbedError::NoRuntime, "no tokio runtime"),
60            (
61                EmbedError::Blueprint("bad".to_string()),
62                "blueprint error: bad",
63            ),
64            (EmbedError::Spawn("nope".to_string()), "spawn error: nope"),
65            (
66                EmbedError::ProviderClient("no roots".to_string()),
67                "provider HTTPS client error: no roots",
68            ),
69            (EmbedError::ChannelClosed, "shut down"),
70        ];
71        for (err, needle) in cases {
72            assert!(err.to_string().contains(needle));
73        }
74    }
75}