Skip to main content

cloudflare_quick_tunnel/
error.rs

1//! Typed error model for the quick-tunnel client. Each variant
2//! corresponds to a distinct failure mode that callers can act on
3//! independently (API rejection vs DNS gap vs handshake refused vs
4//! permanent supervisor giveup).
5
6use thiserror::Error;
7
8/// Business-level error returned inside the API response body when
9/// `success = false`. Mirrors cloudflared's `QuickTunnelError`.
10#[derive(Debug, Clone, serde::Deserialize)]
11pub struct QuickTunnelApiError {
12    pub code: i32,
13    pub message: String,
14}
15
16#[derive(Error, Debug)]
17pub enum TunnelError {
18    #[error("quick-tunnel API request failed: {0}")]
19    Api(#[from] reqwest::Error),
20
21    #[error("quick-tunnel API returned business errors: {0:?}")]
22    ApiBusiness(Vec<QuickTunnelApiError>),
23
24    #[error("quick-tunnel API responded non-JSON ({status}): {body_snippet}")]
25    ApiNonJson { status: u16, body_snippet: String },
26
27    #[error("edge discovery failed: {0}")]
28    Discovery(String),
29
30    #[error("QUIC dial failed after {attempts} attempt(s); last: {last}")]
31    QuicDial { attempts: usize, last: String },
32
33    #[error("capnp-RPC RegisterConnection failed: {0}")]
34    Register(String),
35
36    #[error("connection lost; supervisor giving up after {0} attempts")]
37    PermanentFailure(u32),
38
39    #[error("shutdown requested")]
40    Shutdown,
41
42    #[error("internal invariant violated: {0}")]
43    Internal(String),
44}