Skip to main content

codetether_browser/browser/
error.rs

1use thiserror::Error;
2
3#[allow(dead_code)]
4#[derive(Debug, Error)]
5pub enum BrowserError {
6    #[error("browser command is not implemented: {0}")]
7    NotImplemented(String),
8    #[error("navigation timed out")]
9    NavigationTimeout,
10    #[error("element not found: {0}")]
11    ElementNotFound(String),
12    #[error("element is not fillable: tag={tag}, input_type={input_type:?}")]
13    ElementNotFillable {
14        tag: String,
15        input_type: Option<String>,
16    },
17    #[error("element is not a file input: tag={tag}, input_type={input_type:?}")]
18    ElementNotFileInput {
19        tag: String,
20        input_type: Option<String>,
21    },
22    #[error("file does not exist: {0}")]
23    FileNotFound(String),
24    #[error("file input does not accept multiple files: {0}")]
25    MultipleFilesNotAllowed(String),
26    #[error("waiting for selector timed out: {selector} after {timeout_ms}ms")]
27    WaitTimeout { selector: String, timeout_ms: u64 },
28    #[error("tab not found: {0}")]
29    TabNotFound(usize),
30    #[error("javascript exception: {message}{stack_suffix}", stack_suffix = stack_suffix(.stack.as_deref()))]
31    JsException {
32        message: String,
33        stack: Option<String>,
34    },
35    #[error("browser session not started")]
36    SessionNotStarted,
37    #[error("tab is closed")]
38    TabClosed,
39    #[error("browser crashed or connection was lost")]
40    BrowserCrashed,
41    #[error("evaluation timed out")]
42    EvaluationTimeout,
43    #[error("evaluation promise rejected: {message}")]
44    EvalRejection { message: String },
45    #[error(
46        "evaluation returned non-serializable value: {description} (type={type_}, subtype={subtype:?})"
47    )]
48    EvalNonSerializable {
49        type_: String,
50        subtype: Option<String>,
51        description: String,
52    },
53    #[error("evaluation wrapper error: {0}")]
54    EvalWrapperError(String),
55    #[error("browser operation failed: {0}")]
56    OperationFailed(String),
57}
58
59impl From<anyhow::Error> for BrowserError {
60    fn from(error: anyhow::Error) -> Self {
61        Self::OperationFailed(error.to_string())
62    }
63}
64
65impl From<serde_json::Error> for BrowserError {
66    fn from(error: serde_json::Error) -> Self {
67        Self::OperationFailed(error.to_string())
68    }
69}
70
71fn stack_suffix(stack: Option<&str>) -> String {
72    stack.map(|value| format!("\n{value}")).unwrap_or_default()
73}