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_INVALIDInvalid configuration provided
WEBMCP_API_KEY_MISSINGAPI key is required for this operation
WEBMCP_MODEL_UNSUPPORTEDSpecified AI model is not supported
Processing Errors
Errors during HTML parsing and element processing
WEBMCP_PARSE_ERRORFailed to parse HTML content
WEBMCP_ELEMENT_NOT_FOUNDSpecified element not found
WEBMCP_VALIDATION_FAILEDwebMCP data failed validation
Network Errors
API communication and network-related issues
WEBMCP_NETWORK_TIMEOUTRequest timed out
WEBMCP_API_RATE_LIMITAPI rate limit exceeded
WEBMCP_API_UNAUTHORIZEDAPI authentication failed
Security Errors
Authentication, authorization, and security issues
WEBMCP_CSRF_VALIDATION_FAILEDCSRF token validation failed
WEBMCP_JWT_INVALIDJWT token is invalid or expired
WEBMCP_ENCRYPTION_FAILEDFailed to encrypt sensitive data
Error Handling Patterns
Proven patterns for robust error handling in your applications
Basic Error Handling
Simple try-catch pattern for error handling
JavaScriptimport { 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
JavaScriptclass 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
Pythonfrom 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
JavaScriptimport { 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'
});Validation Mode
Enable strict validation to catch issues early
Usage:
const result = processor.parseWebMCP(html, {
strict: true,
validateSchema: true
});Performance Profiling
Monitor processing performance and bottlenecks
Usage:
const processor = new WebMCPProcessor({
profiling: true,
performanceCallbacks: {
onStep: (step, duration) => console.log(`${step}: ${duration}ms`)
}
});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);
}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