/**
* Custom error classes for different failure types
*/
export class APIError extends Error {
constructor(
message: string,
public statusCode?: number,
public provider?: string,
public originalError?: unknown
) {
super(message);
this.name = 'APIError';
}
}
export class ValidationError extends Error {
constructor(message: string, public field?: string) {
super(message);
this.name = 'ValidationError';
}
}
export class TimeoutError extends Error {
constructor(message: string, public timeoutMs?: number) {
super(message);
this.name = 'TimeoutError';
}
}
export class RateLimitError extends Error {
constructor(message: string, public retryAfter?: number) {
super(message);
this.name = 'RateLimitError';
}
}
export class DataSourceError extends Error {
constructor(
message: string,
public source: string,
public fallbackAvailable: boolean = false
) {
super(message);
this.name = 'DataSourceError';
}
}
/**
* Error logging utility
*/
export const logError = (error: Error, context?: string): void => {
const timestamp = new Date().toISOString();
const contextStr = context ? ` [${context}]` : '';
console.error(`${timestamp}${contextStr} ${error.name}: ${error.message}`);
if (error instanceof APIError && error.originalError) {
console.error('Original error:', error.originalError);
}
if (error.stack) {
console.error('Stack trace:', error.stack);
}
};
/**
* Convert user-friendly error messages for MCP responses
*/
export const formatUserError = (error: Error): string => {
if (error instanceof ValidationError) {
return `Invalid input${error.field ? ` for ${error.field}` : ''}: ${error.message}`;
}
if (error instanceof TimeoutError) {
return 'Request timed out. Please try again.';
}
if (error instanceof RateLimitError) {
const retryMsg = error.retryAfter
? ` Please try again in ${error.retryAfter} seconds.`
: ' Please try again later.';
return `Rate limit exceeded.${retryMsg}`;
}
if (error instanceof DataSourceError) {
const fallbackMsg = error.fallbackAvailable
? ' Attempting to use alternative data source.'
: '';
return `Data source unavailable: ${error.source}.${fallbackMsg}`;
}
if (error instanceof APIError) {
return `Service temporarily unavailable${error.provider ? ` (${error.provider})` : ''}. Please try again.`;
}
return 'An unexpected error occurred. Please try again.';
};