Skip to main content

codetether_agent/browser/
error.rs

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