testdriver-agent
How the TestDriver agent behaves on GitHub issues, pull requests, and @mentions
Custom error classes and error handling
$ npx -y skills add testdriverai/testdriverai --skill testdriver-errors --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
/testdriver-errorsContext preview
The summary Claude sees to decide when to auto-load this skill.
Custom error classes and error handling
name: testdriver:errors description: Custom error classes and error handling
<!-- Generated from errors.mdx. DO NOT EDIT. -->
TestDriver provides custom error classes with rich debugging information. These are exported from the SDK and can be used for `instanceof` checks in your tests.
import TestDriver, { ElementNotFoundError, AIError } from 'testdriverai';Thrown when `find()` cannot locate an element on screen, or when calling `click()`/`hover()` on an unfound element.
try {
await testdriver.find('nonexistent button').click();
} catch (error) {
if (error instanceof ElementNotFoundError) {
console.log(error.description); // "nonexistent button"
console.log(error.screenshotPath); // path to debug screenshot
console.log(error.pixelDiffPath); // path to pixel diff image
}
}<ParamField path="name" type="string"> Always `"ElementNotFoundError"`. </ParamField>
<ParamField path="message" type="string"> Enhanced message with a debug block containing element description, cache status, similarity scores, and AI response details. </ParamField>
<ParamField path="description" type="string"> The original element description passed to `find()`. </ParamField>
<ParamField path="screenshotPath" type="string | null"> Absolute path to a debug screenshot saved at the time of failure. Written to `<os.tmpdir>/testdriver-debug/screenshot-<timestamp>.png`. </ParamField>
<ParamField path="pixelDiffPath" type="string | null"> Absolute path to a pixel diff image showing the comparison between the cached and current screenshots. Written to `<os.tmpdir>/testdriver-debug/pixel-diff-error-<timestamp>.png`. Only present when cache was involved. </ParamField>
<ParamField path="cachedImagePath" type="string | null"> URL to the cached image that was compared against. </ParamField>
<ParamField path="aiResponse" type="object | null"> Sanitized AI response object. Large binary fields (`croppedImage`, `screenshot`, `pixelDiffImage`) are removed. Contains cache metadata like `similarity`, `cacheHit`, `cacheStrategy`, `cacheDiffPercent`, and `threshold`. </ParamField>
<ParamField path="timestamp" type="string"> ISO 8601 timestamp of when the error was created. </ParamField>
The error message is automatically enhanced with debugging information:
Element not found: "submit button" === Element Debug Info === Element: submit button Cache Hit: false Similarity: 0.23 Cache Strategy: pixel-diff Threshold: 0.05 AI Response Element: null
Stack traces are automatically cleaned to remove internal SDK frames (`Element.*`, `sdk.js` internals), showing only your test code for easier debugging.
Thrown when `act()` exhausts all retry attempts.
try {
await testdriver.act('perform complex workflow', { tries: 3 });
} catch (error) {
if (error instanceof AIError) {
console.log(error.task); // "perform complex workflow"
console.log(error.tries); // 3
console.log(error.duration); // 15234 (ms)
console.log(error.cause); // underlying Error
}
}<ParamField path="name" type="string"> Always `"AIError"`. </ParamField>
<ParamField path="message" type="string"> Enhanced message with execution details block. </ParamField>
<ParamField path="task" type="string"> The task description passed to `act()`. </ParamField>
<ParamField path="tries" type="number"> Number of attempts that were made. </ParamField>
<ParamField path="maxTries" type="number"> Maximum number of attempts configured. </ParamField>
<ParamField path="duration" type="number"> Total execution time in milliseconds. </ParamField>
<ParamField path="cause" type="Error | undefined"> The underlying error that caused the final failure. </ParamField>
<ParamField path="timestamp" type="string"> ISO 8601 timestamp of when the error was created. </ParamField>
AI failed: Element not found after 3 attempts === AI Execution Details === Task: perform complex workflow Tries: 3 / 3 Duration: 15234ms Cause: ElementNotFoundError: Element not found: "submit button"
These errors are used internally by the agent and are not exported, but may appear as the `cause` of an `AIError`:
Thrown when element matching fails (text, image, or assertion).
| Property | Type | Description | |---|---|---| | `fatal` | `boolean` | If `true`, cannot be healed. Default: `false` | | `attachScreenshot` | `boolean` | Always `true` — a screenshot is attached to the error |
Thrown for invalid arguments or unsupported operations.
| Property | Type | Description | |---|---|---| | `fatal` | `boolean` | Always `true` | | `attachScreenshot` | `boolean` | Always `false` |
Inside `act()`, assertions run in **soft assert mode**. When an assertion fails, it returns the failure result instead of throwing, allowing the AI to process the failure and adjust its approach.
// Inside act(), assertion failures don't throw
await testdriver.act('verify the dashboard shows correct data', {
tries: 3,
});
// The AI can see assertion results and self-correctThis is automatic — you don't need to configure it. Regular `assert()` calls outside of `act()` will throw normally on failure.
import TestDriver, { ElementNotFoundError, AIError } from 'testdriverai';
try {
await testdriver.find('submit button').click();
} catch (error) {
if (error instanceof ElementNotFoundError) {
// Element wasn't found — check screenshot for debugging
console.log('Debug screenshot:', error.screenshotPath);
} else if (error instanceof AIError) {
// AI exhausted retries
console.log(`Failed after ${error.tries} tries in ${error.duration}Repo: testdriverai/testdriverai
How the TestDriver agent behaves on GitHub issues, pull requests, and @mentions
Deploy TestDriver on your AWS infrastructure using CloudFormation
How TestDriver learns your app and caches what it discovers for instant, deterministic replays