rlmesh_runtime/driver/
error.rs1use std::time::Duration;
4
5use crate::hooks::HookError;
6
7pub type BoxError = Box<dyn std::error::Error + Send + Sync + 'static>;
9
10#[derive(Debug, thiserror::Error)]
11#[non_exhaustive]
12pub enum RuntimeError {
13 #[error("invalid runtime session spec: {0}")]
14 InvalidSpec(String),
15
16 #[error(
17 "{operation} timed out on route {route_id} component {component_id} at runtime step {step} after {timeout:?}"
18 )]
19 OperationTimeout {
20 route_id: String,
21 component_id: String,
22 operation: &'static str,
23 step: i64,
24 timeout: Duration,
25 },
26
27 #[error("route {route_id} cancelled at runtime step {step}: {reason}")]
28 RouteCancelled {
29 route_id: String,
30 step: i64,
31 reason: String,
32 },
33
34 #[error(
35 "environment {operation} failed at runtime step {step}: {message}. If the source is 'transport error: connection closed', the environment server exited, crashed, or received SIGTERM before replying; inspect the environment container logs immediately before the runtime error timestamp"
36 )]
37 EnvRpc {
38 operation: &'static str,
39 step: i64,
40 message: String,
41 recoverable: bool,
44 #[source]
48 source: Option<BoxError>,
49 },
50
51 #[error("model endpoint {component_id} request failed: {message}")]
52 ModelRpc {
53 component_id: String,
54 message: String,
55 recoverable: bool,
57 #[source]
58 source: Option<BoxError>,
59 },
60
61 #[error(
62 "model endpoint {component_id} returned mismatched route identity for request {request_id}"
63 )]
64 ModelRouteMismatch {
65 component_id: String,
66 request_id: String,
67 },
68
69 #[error("protocol error: {0}")]
70 Protocol(String),
71
72 #[error("runtime hook failed: {0}")]
73 Hook(HookError),
74}
75
76impl RuntimeError {
77 pub fn operation_timeout(
78 route_id: impl Into<String>,
79 component_id: impl Into<String>,
80 operation: &'static str,
81 step: i64,
82 timeout: Duration,
83 ) -> Self {
84 Self::OperationTimeout {
85 route_id: route_id.into(),
86 component_id: component_id.into(),
87 operation,
88 step,
89 timeout,
90 }
91 }
92
93 pub fn route_cancelled(
94 route_id: impl Into<String>,
95 step: i64,
96 reason: impl Into<String>,
97 ) -> Self {
98 Self::RouteCancelled {
99 route_id: route_id.into(),
100 step,
101 reason: reason.into(),
102 }
103 }
104
105 pub fn env_rpc<E>(operation: &'static str, step: i64, source: E) -> Self
108 where
109 E: std::error::Error + Send + Sync + 'static,
110 {
111 Self::env_rpc_with_recoverability(operation, step, false, source)
112 }
113
114 pub fn env_rpc_with_recoverability<E>(
118 operation: &'static str,
119 step: i64,
120 recoverable: bool,
121 source: E,
122 ) -> Self
123 where
124 E: std::error::Error + Send + Sync + 'static,
125 {
126 Self::EnvRpc {
127 operation,
128 step,
129 message: source.to_string(),
130 recoverable,
131 source: Some(Box::new(source)),
132 }
133 }
134
135 pub fn model_rpc<E>(component_id: impl Into<String>, source: E) -> Self
138 where
139 E: std::error::Error + Send + Sync + 'static,
140 {
141 Self::model_rpc_with_recoverability(component_id, false, source)
142 }
143
144 pub fn model_rpc_with_recoverability<E>(
147 component_id: impl Into<String>,
148 recoverable: bool,
149 source: E,
150 ) -> Self
151 where
152 E: std::error::Error + Send + Sync + 'static,
153 {
154 Self::ModelRpc {
155 component_id: component_id.into(),
156 message: source.to_string(),
157 recoverable,
158 source: Some(Box::new(source)),
159 }
160 }
161
162 pub fn is_recoverable(&self) -> bool {
168 match self {
169 Self::EnvRpc { recoverable, .. } | Self::ModelRpc { recoverable, .. } => *recoverable,
170 _ => false,
171 }
172 }
173}