Skip to main content

lineark_sdk/
error.rs

1use serde::{Deserialize, Serialize};
2use std::fmt;
3
4/// A single GraphQL error from the API response.
5#[derive(Debug, Clone, Serialize, Deserialize)]
6pub struct GraphQLError {
7    pub message: String,
8    #[serde(default)]
9    pub extensions: Option<serde_json::Value>,
10}
11
12/// Errors that can occur when interacting with the Linear API.
13#[derive(Debug)]
14pub enum LinearError {
15    /// Authentication failed (invalid or expired token).
16    Authentication(String),
17    /// Request was rate-limited.
18    RateLimited {
19        retry_after: Option<f64>,
20        message: String,
21    },
22    /// Invalid input (bad arguments to a mutation).
23    InvalidInput(String),
24    /// Forbidden (insufficient permissions).
25    Forbidden(String),
26    /// Network or HTTP transport error.
27    Network(reqwest::Error),
28    /// GraphQL errors returned by the API.
29    GraphQL(Vec<GraphQLError>),
30    /// The requested data path was not found in the response.
31    MissingData(String),
32    /// Auth configuration error (no token found).
33    AuthConfig(String),
34}
35
36impl fmt::Display for LinearError {
37    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
38        match self {
39            Self::Authentication(msg) => write!(f, "Authentication error: {}", msg),
40            Self::RateLimited { message, .. } => write!(f, "Rate limited: {}", message),
41            Self::InvalidInput(msg) => write!(f, "Invalid input: {}", msg),
42            Self::Forbidden(msg) => write!(f, "Forbidden: {}", msg),
43            Self::Network(e) => write!(f, "Network error: {}", e),
44            Self::GraphQL(errors) => {
45                let msgs: Vec<String> = errors
46                    .iter()
47                    .map(|e| {
48                        if let Some(ext) = &e.extensions {
49                            format!("{} ({})", e.message, ext)
50                        } else {
51                            e.message.clone()
52                        }
53                    })
54                    .collect();
55                write!(f, "GraphQL errors: {}", msgs.join("; "))
56            }
57            Self::MissingData(path) => write!(f, "Missing data at path: {}", path),
58            Self::AuthConfig(msg) => write!(f, "Auth configuration error: {}", msg),
59        }
60    }
61}
62
63impl std::error::Error for LinearError {
64    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
65        match self {
66            Self::Network(e) => Some(e),
67            _ => None,
68        }
69    }
70}
71
72impl From<reqwest::Error> for LinearError {
73    fn from(e: reqwest::Error) -> Self {
74        Self::Network(e)
75    }
76}