testdriver-agent
How the TestDriver agent behaves on GitHub issues, pull requests, and @mentions
Custom error classes and error handling
Claude Code
$ npx -y skills add testdriverai/testdriverai --skill testdriver-errors --agent claude-code
Codex
$ npx skills add testdriverai/testdriverai --skill testdriver-errors -a codex -y
Cursor
$ npx skills add testdriverai/testdriverai --skill testdriver-errors -a cursor -y
Gemini CLI
$ npx skills add testdriverai/testdriverai --skill testdriver-errors -a gemini-cli -y
GitHub Copilot
$ npx skills add testdriverai/testdriverai --skill testdriver-errors -a github-copilot -y
OpenCode
$ npx skills add testdriverai/testdriverai --skill testdriver-errors -a opencode -y
Windsurf
$ npx skills add testdriverai/testdriverai --skill testdriver-errors -a windsurf -y
name: testdriver:errors description: Custom error classes and error handling
<!-- Generated from errors.mdx. DO NOT EDIT. -->
TestDriver gives custom error classes with full debug information. The SDK exports them. You can use them for `instanceof` checks in your tests.
import TestDriver, { ElementNotFoundError, AIError } from 'testdriverai';TestDriver throws this when `find()` cannot find an element on the screen. It also throws this when you call `click()` or `hover()` on an element that TestDriver did not find.
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"> A message with a debug block. The block has the element description, the cache status, the similarity scores, and the 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.loHow 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
Produce the "Playwright 1.xx API Review" artifact for a range of commits - the public API additions and the breaking or behavior…
Write, refine, run, and QA promptfoo evaluation suites: promptfooconfig.yaml, prompts, providers, vars, tests, assertions,…
DeepEval evaluation workflow for AI agents and LLM applications. TRIGGER when the user wants to evaluate or improve an AI agent,…