Skip to main content
Glama
error-handling.md9.94 kB
# DeepSource MCP Server Error Handling Guide ## Overview The DeepSource MCP Server implements a comprehensive error handling system that provides consistent, informative error responses across all tool handlers. This guide explains the error handling architecture, patterns, and best practices. ## Architecture ### Error Classification System The error handling system classifies errors into categories for better debugging and user experience: ```typescript enum ErrorCategory { AUTHENTICATION = 'authentication', AUTHORIZATION = 'authorization', NETWORK = 'network', RATE_LIMIT = 'rate_limit', VALIDATION = 'validation', NOT_FOUND = 'not_found', GRAPHQL = 'graphql', INTERNAL = 'internal', CONFIGURATION = 'configuration', } ``` ### Core Components 1. **Error Factory (`src/utils/errors/factory.ts`)** - Creates classified errors with consistent structure - Preserves original error context - Adds metadata for debugging 2. **Error Handlers (`src/utils/errors/handlers.ts`)** - Specialized handlers for different error types - GraphQL error parsing - HTTP status code mapping - User-friendly message generation 3. **MCP Error Utilities (`src/utils/error-handling/mcp-errors.ts`)** - Tool-specific error handling - Response formatting - Error logging integration ## Error Flow ``` User Request → Tool Handler → Domain Layer → Infrastructure Layer ↓ ↓ ↓ Error Caught Error Caught Error Thrown ↓ ↓ ↓ Classify Transform Create ↓ ↓ ↓ Format Response ← Log Error ← Add Context ``` ## Error Types and Handling ### Authentication Errors **When:** API key is missing, invalid, or expired ```typescript // Example error response { "error": "Authentication error: Invalid or expired API key", "details": "Please check your DEEPSOURCE_API_KEY environment variable" } ``` **Common causes:** - Missing `DEEPSOURCE_API_KEY` environment variable - Expired API key - Invalid API key format ### Network Errors **When:** Network timeouts, connection failures ```typescript // Example error response { "error": "Network error: Connection timeout", "details": "Failed to connect to DeepSource API" } ``` **Common causes:** - Network connectivity issues - DeepSource API downtime - Firewall/proxy blocking ### GraphQL Errors **When:** GraphQL query failures, schema mismatches ```typescript // Example error response { "error": "GraphQL error: Field 'invalidField' not found", "details": "The requested field does not exist in the schema" } ``` **Common causes:** - API version mismatch - Invalid query structure - Schema changes ### Validation Errors **When:** Invalid parameters, missing required fields ```typescript // Example error response { "error": "Validation error: Missing required parameter 'projectKey'", "details": "The projectKey parameter is required for this operation" } ``` **Common causes:** - Missing required parameters - Invalid parameter types - Out-of-range values ### Rate Limit Errors **When:** API rate limits exceeded ```typescript // Example error response { "error": "Rate limit exceeded", "details": "Please wait 60 seconds before retrying" } ``` ## Implementation Examples ### Basic Error Handling in Handlers ```typescript export async function handleProjects(deps: ProjectsHandlerDeps): Promise<ApiResponse> { try { const projects = await deps.projectRepository.findAll(); return { content: [ { type: 'text', text: JSON.stringify({ projects }), }, ], }; } catch (error) { deps.logger.error('Error in handleProjects', { error }); // Error is automatically classified and formatted return createErrorResponse(error); } } ``` ### Custom Error Handling ```typescript export const createQualityMetricsHandler = createBaseHandlerFactory( 'quality_metrics', async (deps, params) => { try { const metrics = await deps.repository.getMetrics(params.projectKey); // Custom validation if (metrics.length === 0) { throw createClassifiedError('No metrics found for project', ErrorCategory.NOT_FOUND, null, { projectKey: params.projectKey, }); } return formatMetricsResponse(metrics); } catch (error) { // Base handler factory automatically handles errors throw error; } } ); ``` ### Error Context Preservation ```typescript try { const result = await apiCall(); } catch (error) { // Preserve original error while adding context throw createClassifiedError( 'Failed to fetch project data', ErrorCategory.NETWORK, error, // Original error preserved { projectKey: params.projectKey, attempt: retryCount, } ); } ``` ## Best Practices ### 1. Use Error Classification Always classify errors to help with debugging and monitoring: ```typescript // Good throw createClassifiedError('Project not found', ErrorCategory.NOT_FOUND, null, { projectKey }); // Avoid throw new Error('Project not found'); ``` ### 2. Preserve Error Context Always preserve the original error when rethrowing: ```typescript // Good catch (error) { throw createClassifiedError( 'Failed to process request', ErrorCategory.INTERNAL, error, // Original error preserved { context: 'additional info' } ); } // Avoid catch (error) { throw new Error('Failed to process request'); } ``` ### 3. Provide Actionable Error Messages Error messages should guide users to resolution: ```typescript // Good { error: "Authentication failed: Invalid API key", details: "Please verify your DEEPSOURCE_API_KEY in environment variables" } // Avoid { error: "Error", details: "Something went wrong" } ``` ### 4. Log Errors Appropriately Use appropriate log levels: ```typescript // Authentication/validation errors - expected logger.warn('Invalid API key provided', { maskedKey }); // Network/internal errors - unexpected logger.error('Unexpected error in handler', { error, stack }); ``` ### 5. Handle Async Errors Always handle promises and async operations: ```typescript // Good - errors are caught by handler factory export const handler = createBaseHandlerFactory('tool_name', async (deps, params) => { const result = await asyncOperation(); // Errors automatically caught return formatResponse(result); }); // Manual error handling when needed try { const results = await Promise.all([operation1(), operation2()]); } catch (error) { // Handle aggregated errors } ``` ## Error Response Format All errors follow a consistent response format: ```typescript interface ErrorResponse { content: [ { type: 'text'; text: string; // JSON stringified error object }, ]; isError: true; } interface ErrorObject { error: string; // Human-readable error message details?: string; // Additional context code?: string; // Error code (e.g., 'AUTH_001') metadata?: object; // Debug information (not shown to users) } ``` ## Monitoring and Debugging ### Error Logging All errors are logged with context: ```typescript logger.error('Handler failed', { handler: 'quality_metrics', error: error.message, category: error.category, metadata: error.metadata, stack: error.stack, }); ``` ### Debug Mode Enable debug logging for detailed error information: ```bash export LOG_LEVEL=DEBUG ``` ### Common Error Patterns 1. **Authentication Chain** ``` API Key Missing → Check Environment → Return Configuration Error API Key Invalid → GraphQL 401 → Return Authentication Error ``` 2. **Network Failures** ``` Connection Timeout → Retry Logic → Return Network Error DNS Failure → No Retry → Return Network Error ``` 3. **GraphQL Errors** ``` Field Error → Parse GraphQL Response → Return Validation Error Query Error → Check Schema → Return GraphQL Error ``` ## Testing Error Handling ### Unit Tests ```typescript it('should handle authentication errors', async () => { const error = new Error('401 Unauthorized'); mockClient.listProjects.mockRejectedValue(error); const result = await handler({ projectKey: 'test' }); expect(result.isError).toBe(true); expect(JSON.parse(result.content[0].text)).toMatchObject({ error: expect.stringContaining('Authentication error'), }); }); ``` ### Integration Tests ```typescript it('should handle network timeouts gracefully', async () => { const timeoutError = new Error('ETIMEDOUT'); mockApiCall.mockRejectedValue(timeoutError); const result = await callTool('projects'); expect(result.isError).toBe(true); expect(result.content[0].text).toContain('Network error'); }); ``` ## Troubleshooting ### Common Issues 1. **"Cannot read property of undefined"** - Usually indicates missing error handling in async code - Check for unhandled promise rejections 2. **"Maximum call stack exceeded"** - Error handler throwing errors - Circular error handling logic 3. **Silent Failures** - Errors caught but not logged - Check error handler middleware ### Debug Checklist - [ ] Check environment variables - [ ] Verify API key validity - [ ] Check network connectivity - [ ] Review error logs - [ ] Test with debug logging enabled - [ ] Verify error handler registration ## Future Improvements 1. **Retry Logic** - Automatic retry for transient errors - Exponential backoff for rate limits 2. **Error Aggregation** - Collect related errors - Provide comprehensive error reports 3. **Error Recovery** - Graceful degradation - Fallback strategies 4. **Monitoring Integration** - Error tracking service integration - Performance monitoring - Alert configuration

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/sapientpants/deepsource-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server