Error Handling

Comprehensive error handling guide for webMCP. Learn to handle errors gracefully and build robust applications.

Error Categories

Common error types and their solutions

Configuration Errors

Issues with webMCP configuration and setup

WEBMCP_CONFIG_INVALID

Invalid configuration provided

Cause: Malformed configuration object or missing required fields
Solution: Validate configuration against schema and ensure all required fields are present
WEBMCP_API_KEY_MISSING

API key is required for this operation

Cause: Premium feature accessed without valid API key
Solution: Set WEBMCP_API_KEY environment variable or pass api_key in configuration
WEBMCP_MODEL_UNSUPPORTED

Specified AI model is not supported

Cause: Invalid model name or model not available in current plan
Solution: Use supported model names: gpt-4o, claude-3.5-sonnet, gpt-4, etc.

Processing Errors

Errors during HTML parsing and element processing

WEBMCP_PARSE_ERROR

Failed to parse HTML content

Cause: Malformed HTML or unsupported content structure
Solution: Validate HTML structure and ensure proper encoding
WEBMCP_ELEMENT_NOT_FOUND

Specified element not found

Cause: CSS selector does not match any elements on the page
Solution: Verify selector syntax and ensure elements exist in the DOM
WEBMCP_VALIDATION_FAILED

webMCP data failed validation

Cause: Generated webMCP data does not conform to schema
Solution: Check element structure and ensure all required properties are present

Network Errors

API communication and network-related issues

WEBMCP_NETWORK_TIMEOUT

Request timed out

Cause: Network request exceeded configured timeout
Solution: Increase timeout value or check network connectivity
WEBMCP_API_RATE_LIMIT

API rate limit exceeded

Cause: Too many requests sent in a short period
Solution: Implement exponential backoff and respect rate limits
WEBMCP_API_UNAUTHORIZED

API authentication failed

Cause: Invalid or expired API key
Solution: Verify API key is correct and has not expired

Security Errors

Authentication, authorization, and security issues

WEBMCP_CSRF_VALIDATION_FAILED

CSRF token validation failed

Cause: Invalid or missing CSRF token
Solution: Generate new CSRF token and include in request headers
WEBMCP_JWT_INVALID

JWT token is invalid or expired

Cause: Token signature invalid or token past expiration time
Solution: Generate new JWT token with valid signature and expiration
WEBMCP_ENCRYPTION_FAILED

Failed to encrypt sensitive data

Cause: Encryption key missing or malformed
Solution: Verify encryption configuration and key format

Error Handling Patterns

Proven patterns for robust error handling in your applications

Basic Error Handling

Simple try-catch pattern for error handling

JavaScript
import { WebMCPProcessor, WebMCPError } from '@webmcp/core';

const processor = new WebMCPProcessor();

try {
  const result = processor.parseWebMCP(htmlContent);
  console.log('Success:', result);
} catch (error) {
  if (error instanceof WebMCPError) {
    console.error('webMCP Error:', {
      code: error.code,
      message: error.message,
      details: error.details
    });
    
    // Handle specific error types
    switch (error.code) {
      case 'WEBMCP_PARSE_ERROR':
        console.log('HTML parsing failed, check HTML structure');
        break;
      case 'WEBMCP_API_KEY_MISSING':
        console.log('API key required for this operation');
        break;
      default:
        console.log('Unknown webMCP error:', error.code);
    }
  } else {
    console.error('Unexpected error:', error);
  }
}

Advanced Error Handling

Comprehensive error handling with retry logic

JavaScript
class WebMCPErrorHandler {
  constructor(maxRetries = 3, retryDelay = 1000) {
    this.maxRetries = maxRetries;
    this.retryDelay = retryDelay;
  }

  async processWithRetry(processor, htmlContent, options = {}) {
    let lastError;
    
    for (let attempt = 1; attempt <= this.maxRetries; attempt++) {
      try {
        return await processor.parseWebMCP(htmlContent, options);
      } catch (error) {
        lastError = error;
        
        if (this.shouldRetry(error) && attempt < this.maxRetries) {
          console.warn(`Attempt ${attempt} failed, retrying in ${this.retryDelay}ms`);
          await this.delay(this.retryDelay * attempt); // Exponential backoff
          continue;
        }
        
        throw this.enrichError(error, attempt);
      }
    }
  }

  shouldRetry(error) {
    const retryableCodes = [
      'WEBMCP_NETWORK_TIMEOUT',
      'WEBMCP_API_RATE_LIMIT',
      'WEBMCP_TEMPORARY_ERROR'
    ];
    return retryableCodes.includes(error.code);
  }

  enrichError(error, attempts) {
    return new WebMCPError(error.code, error.message, {
      ...error.details,
      attempts,
      timestamp: new Date().toISOString()
    });
  }

  delay(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
  }
}

Python Error Handling

Error handling patterns for Python implementation

Python
from webmcp_core import WebMCPProcessor, WebMCPError
import logging
import time
import random

logger = logging.getLogger(__name__)

class WebMCPRetryHandler:
    def __init__(self, max_retries=3, base_delay=1.0):
        self.max_retries = max_retries
        self.base_delay = base_delay
    
    def process_with_retry(self, processor, html_content, **options):
        last_error = None
        
        for attempt in range(1, self.max_retries + 1):
            try:
                return processor.parse_webmcp(html_content, **options)
            except WebMCPError as error:
                last_error = error
                logger.warning(f"Attempt {attempt} failed: {error}")
                
                if self._should_retry(error) and attempt < self.max_retries:
                    delay = self._calculate_delay(attempt)
                    logger.info(f"Retrying in {delay:.2f} seconds...")
                    time.sleep(delay)
                    continue
                
                # Enrich error with retry information
                error.details = error.details or {}
                error.details.update({
                    'attempts': attempt,
                    'max_retries': self.max_retries
                })
                raise error
        
        raise last_error
    
    def _should_retry(self, error):
        retryable_codes = {
            'WEBMCP_NETWORK_TIMEOUT',
            'WEBMCP_API_RATE_LIMIT',
            'WEBMCP_TEMPORARY_ERROR'
        }
        return error.code in retryable_codes
    
    def _calculate_delay(self, attempt):
        # Exponential backoff with jitter
        delay = self.base_delay * (2 ** (attempt - 1))
        jitter = random.uniform(0.1, 0.3) * delay
        return delay + jitter

# Usage example
processor = WebMCPProcessor()
retry_handler = WebMCPRetryHandler(max_retries=3)

try:
    result = retry_handler.process_with_retry(processor, html_content)
    print("Success:", result)
except WebMCPError as error:
    logger.error(f"Processing failed after retries: {error}")
    
    # Handle specific error types
    if error.code == 'WEBMCP_API_KEY_MISSING':
        print("Please set your API key in environment variables")
    elif error.code == 'WEBMCP_PARSE_ERROR':
        print("HTML structure is invalid, please check your markup")
    else:
        print(f"Unexpected error: {error.code} - {error.message}")

Error Monitoring & Logging

Comprehensive error monitoring and structured logging

JavaScript
import { WebMCPProcessor, WebMCPError } from '@webmcp/core';

class WebMCPMonitor {
  constructor(options = {}) {
    this.enableMetrics = options.enableMetrics ?? true;
    this.logLevel = options.logLevel || 'info';
    this.errorThreshold = options.errorThreshold || 10; // errors per minute
    this.metrics = {
      errors: new Map(),
      errorCount: 0,
      lastReset: Date.now()
    };
  }

  async processWithMonitoring(processor, htmlContent, context = {}) {
    const startTime = Date.now();
    const requestId = this.generateRequestId();
    
    try {
      this.logRequest('info', 'Processing started', {
        requestId,
        context,
        timestamp: new Date().toISOString()
      });

      const result = await processor.parseWebMCP(htmlContent);
      
      this.logRequest('info', 'Processing completed', {
        requestId,
        duration: Date.now() - startTime,
        elementCount: result.elements?.length || 0
      });

      return result;
    } catch (error) {
      const errorInfo = {
        requestId,
        duration: Date.now() - startTime,
        error: {
          code: error.code,
          message: error.message,
          stack: error.stack
        },
        context
      };

      this.recordError(error.code);
      this.logRequest('error', 'Processing failed', errorInfo);
      
      // Check if error rate is too high
      if (this.isErrorRateHigh()) {
        this.logRequest('warn', 'High error rate detected', {
          errorCount: this.metrics.errorCount,
          threshold: this.errorThreshold
        });
      }

      throw this.createEnrichedError(error, errorInfo);
    }
  }

  recordError(errorCode) {
    const now = Date.now();
    
    // Reset metrics every minute
    if (now - this.metrics.lastReset > 60000) {
      this.metrics.errors.clear();
      this.metrics.errorCount = 0;
      this.metrics.lastReset = now;
    }

    this.metrics.errors.set(errorCode, (this.metrics.errors.get(errorCode) || 0) + 1);
    this.metrics.errorCount++;
  }

  isErrorRateHigh() {
    return this.metrics.errorCount >= this.errorThreshold;
  }

  createEnrichedError(originalError, errorInfo) {
    const enrichedError = new WebMCPError(
      originalError.code,
      originalError.message,
      {
        ...originalError.details,
        requestId: errorInfo.requestId,
        duration: errorInfo.duration,
        timestamp: new Date().toISOString()
      }
    );
    
    // Copy stack trace
    enrichedError.stack = originalError.stack;
    return enrichedError;
  }

  logRequest(level, message, data) {
    const logEntry = {
      level,
      message,
      service: 'webmcp',
      ...data
    };

    // Send to your logging service
    console[level](JSON.stringify(logEntry));
    
    // Optional: Send to external monitoring service
    if (this.enableMetrics && level === 'error') {
      this.sendToMonitoringService(logEntry);
    }
  }

  sendToMonitoringService(logEntry) {
    // Implementation for external monitoring (e.g., Sentry, DataDog)
    // This is a placeholder
    console.log('Sending to monitoring service:', logEntry);
  }

  generateRequestId() {
    return `webmcp_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
  }

  getMetrics() {
    return {
      errorCount: this.metrics.errorCount,
      errorsByType: Object.fromEntries(this.metrics.errors),
      timeWindow: '1 minute'
    };
  }
}

Debugging Tools

Built-in tools to help diagnose and resolve issues

Verbose Logging

Enable detailed logging for troubleshooting

Usage:

const processor = new WebMCPProcessor({ verbose: true, logLevel: 'debug' });
Get detailed information about processing steps

Validation Mode

Enable strict validation to catch issues early

Usage:

const result = processor.parseWebMCP(html, { strict: true, validateSchema: true });
Catch schema violations and data inconsistencies

Performance Profiling

Monitor processing performance and bottlenecks

Usage:

const processor = new WebMCPProcessor({ profiling: true, performanceCallbacks: { onStep: (step, duration) => console.log(`${step}: ${duration}ms`) } });
Identify performance bottlenecks and optimization opportunities

Error Context

Add contextual information to errors

Usage:

try { processor.parseWebMCP(html); } catch (error) { console.log('Error context:', error.details); console.log('HTML snippet:', error.details?.htmlSnippet); }
Get additional context for debugging errors

Error Handling Best Practices

Guidelines for building resilient applications

Fail Fast

Validate inputs early and fail fast to prevent cascading errors and make debugging easier.

Implement Retries

Use exponential backoff for transient errors like network timeouts and rate limits.

Log Contextually

Include relevant context in error logs: request IDs, user information, and operation details.

Graceful Degradation

Provide fallbacks and alternative flows when non-critical features fail.

Monitor Errors

Set up error monitoring and alerting to catch issues before they impact users.

Set Timeouts

Always set appropriate timeouts for network requests and long-running operations.

Build Resilient Applications

Implement robust error handling to create reliable webMCP applications