playwright_rs/error.rs
1// Error types for playwright-core
2
3use thiserror::Error;
4
5/// Result type alias for playwright-core operations
6pub type Result<T> = std::result::Result<T, Error>;
7
8/// Errors that can occur when using playwright-core
9#[derive(Debug, Error)]
10#[non_exhaustive]
11pub enum Error {
12 /// Playwright server binary was not found
13 ///
14 /// The Playwright Node.js driver could not be located.
15 /// To resolve this, install Playwright using: `npm install playwright`
16 /// Or ensure the PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD environment variable is not set.
17 #[error("Playwright server not found. Install with: npm install playwright")]
18 ServerNotFound,
19
20 /// Failed to launch the Playwright server process
21 ///
22 /// The Playwright server process could not be started.
23 /// Common causes: Node.js not installed, insufficient permissions, or port already in use.
24 /// Details: {0}
25 #[error("Failed to launch Playwright server: {0}. Check that Node.js is installed.")]
26 LaunchFailed(String),
27
28 /// Server error (runtime issue with Playwright server)
29 #[error("Server error: {0}")]
30 ServerError(String),
31
32 /// Browser is not installed
33 ///
34 /// The specified browser has not been installed for the bundled driver.
35 /// To resolve this, install browsers through the crate (version-safe), or
36 /// with the one-off npx command using the exact bundled driver version.
37 #[error(
38 "Browser '{browser_name}' is not installed.\n\n\
39 {message}\n\n\
40 To install {browser_name} from your project (version-safe, rides Cargo.lock):\n \
41 playwright_rs::install_browsers(Some(&[\"{browser_name}\"])).await\n \
42 (see the crate's install-browsers example)\n\n\
43 Or as a one-off shell command:\n \
44 npx playwright@{playwright_version} install {browser_name}\n \
45 (the version must match the bundled driver; avoid hardcoding it in CI)\n\n\
46 See: https://playwright.dev/docs/browsers"
47 )]
48 BrowserNotInstalled {
49 browser_name: String,
50 message: String,
51 playwright_version: String,
52 },
53
54 /// Failed to establish connection with the server
55 #[error("Failed to connect to Playwright server: {0}")]
56 ConnectionFailed(String),
57
58 /// Transport-level error (stdio communication)
59 #[error("Transport error: {0}")]
60 TransportError(String),
61
62 /// Protocol-level error (JSON-RPC)
63 #[error("Protocol error: {0}")]
64 ProtocolError(String),
65
66 /// I/O error
67 #[error("I/O error: {0}")]
68 Io(#[from] std::io::Error),
69
70 /// JSON serialization/deserialization error
71 #[error("JSON error: {0}")]
72 Json(#[from] serde_json::Error),
73
74 /// Timeout waiting for operation
75 ///
76 /// Contains context about what operation timed out and the timeout duration.
77 /// Common causes include slow network, server not responding, or element not becoming actionable.
78 /// Consider increasing the timeout or checking if the target is accessible.
79 #[error("Timeout: {0}")]
80 Timeout(String),
81
82 /// Navigation timeout
83 ///
84 /// Occurs when page navigation exceeds the specified timeout.
85 /// Includes the URL being navigated to and timeout duration.
86 #[error("Navigation timeout after {duration_ms}ms navigating to '{url}'")]
87 NavigationTimeout { url: String, duration_ms: u64 },
88
89 /// Target was closed (browser, context, or page)
90 ///
91 /// Occurs when attempting to perform an operation on a closed target.
92 /// The target must be recreated before it can be used again.
93 #[error("Target closed: Cannot perform operation on closed {target_type}. {context}")]
94 TargetClosed {
95 target_type: String,
96 context: String,
97 },
98
99 /// Unknown protocol object type
100 #[error("Unknown protocol object type: {0}")]
101 UnknownObjectType(String),
102
103 /// Channel closed unexpectedly
104 #[error("Channel closed unexpectedly")]
105 ChannelClosed,
106
107 /// Invalid argument provided to method
108 #[error("Invalid argument: {0}")]
109 InvalidArgument(String),
110
111 /// Element not found by selector
112 ///
113 /// Includes the selector that was used to locate the element.
114 /// This error typically occurs when waiting for an element times out.
115 #[error("Element not found: selector '{0}'")]
116 ElementNotFound(String),
117
118 /// Assertion timeout (expect API)
119 #[error("Assertion timeout: {0}")]
120 AssertionTimeout(String),
121
122 /// Assertion failed (expect API, server returned mismatch without timeout)
123 #[error("Assertion failed: {0}")]
124 AssertionFailed(String),
125 /// Object not found in registry (may have been closed/disposed)
126 #[error("Object not found (may have been closed): {0}")]
127 ObjectNotFound(String),
128
129 /// Type mismatch when downcasting a protocol object
130 ///
131 /// Occurs when a protocol object's concrete type does not match the expected type.
132 /// This typically indicates a Playwright protocol version mismatch or a bug in the
133 /// object factory.
134 #[error("Type mismatch for object '{guid}': expected {expected}, got {actual}")]
135 TypeMismatch {
136 guid: String,
137 expected: String,
138 actual: String,
139 },
140
141 /// Invalid path provided
142 #[error("Invalid path: {0}")]
143 InvalidPath(String),
144
145 /// Error with additional context
146 #[error("{0}: {1}")]
147 Context(String, #[source] Box<Error>),
148}
149
150impl Error {
151 /// Adds context to the error
152 pub fn context(self, msg: impl Into<String>) -> Self {
153 Error::Context(msg.into(), Box::new(self))
154 }
155}