codetether_agent/browser/
error.rs1use 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}