@dorothywebb/any-browser-mcp
Version:
Any Browser MCP - Launch Chrome with your actual data in debug mode for comprehensive browser automation
357 lines • 13.5 kB
JavaScript
/**
* Comprehensive Error Handling System for Any Browser MCP
*
* @fileoverview Provides specific error types for different failure scenarios with detailed
* messages, recovery suggestions, and comprehensive error context. This system enables
* better debugging and user guidance when issues occur.
*
* @example
* ```typescript
* import { ErrorFactory, ErrorCode } from './errors.js';
*
* // Create specific error types
* const connectionError = ErrorFactory.createConnectionError(
* 'Failed to connect to browser',
* { operation: 'checkBrowserAvailability', details: { port: 9223 } }
* );
*
* // Get formatted error message with recovery actions
* console.error(connectionError.getFormattedMessage());
*
* // Convert to JSON for logging
* console.log(JSON.stringify(connectionError.toJSON(), null, 2));
* ```
*
* @category Error Handling
*/
/**
* Enumeration of all possible error codes in the Any Browser MCP system.
*
* @description Each error code represents a specific type of failure that can occur
* during browser automation operations. These codes help categorize errors for
* better handling and user guidance.
*
* @example
* ```typescript
* if (error.code === ErrorCode.CONNECTION_FAILED) {
* // Handle connection-specific errors
* console.log('Browser connection failed');
* } else if (error.code === ErrorCode.TOOL_EXECUTION_FAILED) {
* // Handle tool execution errors
* console.log('Browser tool failed to execute');
* }
* ```
*/
export var ErrorCode;
(function (ErrorCode) {
// Connection Errors
/** Browser connection failed to establish */
ErrorCode["CONNECTION_FAILED"] = "CONNECTION_FAILED";
/** Browser connection timed out */
ErrorCode["CONNECTION_TIMEOUT"] = "CONNECTION_TIMEOUT";
/** Browser connection was refused */
ErrorCode["CONNECTION_REFUSED"] = "CONNECTION_REFUSED";
/** Browser connection was lost during operation */
ErrorCode["CONNECTION_LOST"] = "CONNECTION_LOST";
// Browser Launch Errors
/** Browser executable not found on system */
ErrorCode["BROWSER_NOT_FOUND"] = "BROWSER_NOT_FOUND";
/** Browser failed to launch */
ErrorCode["BROWSER_LAUNCH_FAILED"] = "BROWSER_LAUNCH_FAILED";
/** Browser launch operation timed out */
ErrorCode["BROWSER_LAUNCH_TIMEOUT"] = "BROWSER_LAUNCH_TIMEOUT";
/** Insufficient permissions to launch browser */
ErrorCode["BROWSER_PERMISSION_DENIED"] = "BROWSER_PERMISSION_DENIED";
// Configuration Errors
/** Configuration file is invalid */
ErrorCode["CONFIG_INVALID"] = "CONFIG_INVALID";
/** Configuration file is missing */
ErrorCode["CONFIG_MISSING"] = "CONFIG_MISSING";
/** Configuration validation failed */
ErrorCode["CONFIG_VALIDATION_FAILED"] = "CONFIG_VALIDATION_FAILED";
// Tool Execution Errors
/** Browser tool execution failed */
ErrorCode["TOOL_EXECUTION_FAILED"] = "TOOL_EXECUTION_FAILED";
/** Browser tool execution timed out */
ErrorCode["TOOL_TIMEOUT"] = "TOOL_TIMEOUT";
/** Invalid parameters provided to browser tool */
ErrorCode["TOOL_INVALID_PARAMS"] = "TOOL_INVALID_PARAMS";
/** Element not found on page */
ErrorCode["ELEMENT_NOT_FOUND"] = "ELEMENT_NOT_FOUND";
// Data Errors
/** Failed to copy browser data */
ErrorCode["DATA_COPY_FAILED"] = "DATA_COPY_FAILED";
/** Access denied to browser data */
ErrorCode["DATA_ACCESS_DENIED"] = "DATA_ACCESS_DENIED";
/** Browser data corruption detected */
ErrorCode["DATA_CORRUPTION"] = "DATA_CORRUPTION";
// System Errors
/** Insufficient system permissions */
ErrorCode["INSUFFICIENT_PERMISSIONS"] = "INSUFFICIENT_PERMISSIONS";
/** Required resource unavailable */
ErrorCode["RESOURCE_UNAVAILABLE"] = "RESOURCE_UNAVAILABLE";
/** General system error */
ErrorCode["SYSTEM_ERROR"] = "SYSTEM_ERROR";
})(ErrorCode || (ErrorCode = {}));
export class MCPError extends Error {
code;
context;
recoveryActions;
userFriendly;
constructor(message, code, context = {}, recoveryActions = [], userFriendly = true) {
super(message);
this.name = this.constructor.name;
this.code = code;
this.context = {
...context,
timestamp: new Date()
};
this.recoveryActions = recoveryActions;
this.userFriendly = userFriendly;
// Capture stack trace
if (Error.captureStackTrace) {
Error.captureStackTrace(this, this.constructor);
}
}
/**
* Get a formatted error message with context and recovery suggestions
*/
getFormattedMessage() {
let message = `[${this.code}] ${this.message}`;
if (this.context.operation) {
message += `\n Operation: ${this.context.operation}`;
}
if (this.context.component) {
message += `\n Component: ${this.context.component}`;
}
if (this.context.details && Object.keys(this.context.details).length > 0) {
message += `\n Details: ${JSON.stringify(this.context.details, null, 2)}`;
}
if (this.recoveryActions.length > 0) {
message += `\n\nRecovery Actions:`;
this.recoveryActions.forEach((action, index) => {
message += `\n ${index + 1}. ${action.action}: ${action.description}`;
if (action.command) {
message += `\n Command: ${action.command}`;
}
});
}
return message;
}
/**
* Convert error to JSON for logging or transmission
*/
toJSON() {
return {
name: this.name,
message: this.message,
code: this.code,
context: this.context,
recoveryActions: this.recoveryActions,
userFriendly: this.userFriendly,
stack: this.stack
};
}
}
/**
* Browser Connection Errors
*/
export class BrowserConnectionError extends MCPError {
constructor(message, context = {}, cause) {
const recoveryActions = [
{
action: 'Check Browser Status',
description: 'Ensure Chrome is running with debugging enabled',
command: 'chrome --remote-debugging-port=9223'
},
{
action: 'Verify Port',
description: 'Check if the debug port is available and not blocked',
command: 'curl http://localhost:9223/json/version'
},
{
action: 'Restart Browser',
description: 'Close Chrome completely and restart with debug mode'
}
];
super(message, ErrorCode.CONNECTION_FAILED, { ...context, component: 'BrowserConnection' }, recoveryActions);
if (cause) {
this.context.details = { ...this.context.details, cause: cause.message };
}
}
}
/**
* Browser Launch Errors
*/
export class BrowserLaunchError extends MCPError {
constructor(message, context = {}, cause) {
const recoveryActions = [
{
action: 'Check Chrome Installation',
description: 'Verify Chrome is installed and accessible',
command: 'which chrome || which google-chrome'
},
{
action: 'Check Permissions',
description: 'Ensure Chrome executable has proper permissions'
},
{
action: 'Clear Profile',
description: 'Remove MCP profile directory if corrupted',
command: 'rm -rf ./any-browser-mcp-profile'
}
];
super(message, ErrorCode.BROWSER_LAUNCH_FAILED, { ...context, component: 'ChromeLauncher' }, recoveryActions);
if (cause) {
this.context.details = { ...this.context.details, cause: cause.message };
}
}
}
/**
* Configuration Errors
*/
export class ConfigurationError extends MCPError {
constructor(message, context = {}, validationErrors) {
const recoveryActions = [
{
action: 'Check Config File',
description: 'Verify config.json exists and is valid JSON'
},
{
action: 'Reset Configuration',
description: 'Use default configuration if config is corrupted'
},
{
action: 'Validate Schema',
description: 'Ensure all required configuration fields are present'
}
];
super(message, ErrorCode.CONFIG_VALIDATION_FAILED, { ...context, component: 'ConfigManager', details: { validationErrors } }, recoveryActions);
}
}
/**
* Tool Execution Errors
*/
export class ToolExecutionError extends MCPError {
constructor(toolName, message, context = {}, cause) {
const recoveryActions = [
{
action: 'Retry Operation',
description: 'Wait a moment and try the operation again'
},
{
action: 'Check Browser State',
description: 'Ensure browser is responsive and page is loaded'
},
{
action: 'Verify Parameters',
description: 'Check that all tool parameters are valid'
}
];
super(`Tool '${toolName}' execution failed: ${message}`, ErrorCode.TOOL_EXECUTION_FAILED, { ...context, component: 'BrowserTools', operation: toolName }, recoveryActions);
if (cause) {
this.context.details = { ...this.context.details, cause: cause.message };
}
}
}
/**
* Data Operation Errors
*/
export class DataOperationError extends MCPError {
constructor(operation, message, context = {}, cause) {
const recoveryActions = [
{
action: 'Check Permissions',
description: 'Ensure proper file system permissions for data access'
},
{
action: 'Verify Source Data',
description: 'Check that Chrome user data directory exists and is accessible'
},
{
action: 'Clear Target Directory',
description: 'Remove corrupted MCP profile and retry',
command: 'rm -rf ./any-browser-mcp-profile'
}
];
super(`Data operation '${operation}' failed: ${message}`, ErrorCode.DATA_COPY_FAILED, { ...context, component: 'ChromeLauncher', operation }, recoveryActions);
if (cause) {
this.context.details = { ...this.context.details, cause: cause.message };
}
}
}
/**
* Lazy Initialization Errors
*/
export class LazyInitializationError extends MCPError {
constructor(message, context = {}, cause) {
const recoveryActions = [
{
action: 'Manual Browser Start',
description: 'Start Chrome manually with debugging enabled',
command: 'chrome --remote-debugging-port=9223'
},
{
action: 'Check Configuration',
description: 'Verify MCP configuration allows browser launching'
},
{
action: 'Reset Manager State',
description: 'Clear any cached connection state and retry'
}
];
super(message, ErrorCode.CONNECTION_FAILED, { ...context, component: 'LazyBrowserManager' }, recoveryActions);
if (cause) {
this.context.details = { ...this.context.details, cause: cause.message };
}
}
}
/**
* Element Not Found Errors
*/
export class ElementNotFoundError extends MCPError {
constructor(selector, context = {}) {
const recoveryActions = [
{
action: 'Wait for Element',
description: 'Element might still be loading, wait a moment and retry'
},
{
action: 'Check Selector',
description: 'Verify the CSS selector is correct and specific enough'
},
{
action: 'Inspect Page',
description: 'Use browser dev tools to verify element exists'
}
];
super(`Element not found: ${selector}`, ErrorCode.ELEMENT_NOT_FOUND, { ...context, component: 'BrowserTools', details: { selector } }, recoveryActions);
}
}
/**
* Error Factory for creating appropriate error types
*/
export class ErrorFactory {
static createConnectionError(message, context, cause) {
return new BrowserConnectionError(message, context, cause);
}
static createLaunchError(message, context, cause) {
return new BrowserLaunchError(message, context, cause);
}
static createConfigError(message, context, validationErrors) {
return new ConfigurationError(message, context, validationErrors);
}
static createToolError(toolName, message, context, cause) {
return new ToolExecutionError(toolName, message, context, cause);
}
static createDataError(operation, message, context, cause) {
return new DataOperationError(operation, message, context, cause);
}
static createLazyInitError(message, context, cause) {
return new LazyInitializationError(message, context, cause);
}
static createElementNotFoundError(selector, context) {
return new ElementNotFoundError(selector, context);
}
}
//# sourceMappingURL=errors.js.map