Development

Error Handling Standards

Comprehensive guidelines for handling errors gracefully across frontend and backend applications.

Cursor Add to Cursor
Cursor Rule (.mdc)

Copy this complete rule and save it as a .mdc file in your .cursor/rules directory

# Error Handling Standards

## Core Principles

1. **Fail Fast**: Detect and report errors as early as possible
2. **Fail Gracefully**: Always provide a fallback or recovery path
3. **Be Specific**: Use typed errors with clear messages
4. **Log Appropriately**: Capture context for debugging without leaking sensitive data

## Error Types

### Operational Errors
Expected errors that can be handled gracefully:
- Network failures
- Invalid user input
- Resource not found
- Permission denied

### Programming Errors
Bugs that should be fixed in code:
- Undefined variables
- Type mismatches
- Logic errors

## Implementation Patterns

### TypeScript/JavaScript

```typescript
// Custom error classes
class AppError extends Error {
  constructor(
    message: string,
    public code: string,
    public statusCode: number = 500,
    public isOperational: boolean = true
  ) {
    super(message);
    this.name = this.constructor.name;
    Error.captureStackTrace(this, this.constructor);
  }
}

class ValidationError extends AppError {
  constructor(message: string, public field?: string) {
    super(message, 'VALIDATION_ERROR', 400);
  }
}

class NotFoundError extends AppError {
  constructor(resource: string) {
    super(`${resource} not found`, 'NOT_FOUND', 404);
  }
}
```

### Try-Catch Best Practices

```typescript
// DO: Catch specific errors
try {
  await saveUser(data);
} catch (error) {
  if (error instanceof ValidationError) {
    return { error: error.message, field: error.field };
  }
  if (error instanceof NotFoundError) {
    return { error: 'User not found' };
  }
  // Re-throw unexpected errors
  throw error;
}

// DON'T: Catch and ignore
try {
  await saveUser(data);
} catch (error) {
  // Silent failure - BAD
}
```

### Async Error Handling

```typescript
// Promise chains
fetchData()
  .then(processData)
  .catch(handleError)
  .finally(cleanup);

// Async/await with error boundary
async function fetchWithRetry(url: string, retries = 3): Promise<Response> {
  for (let i = 0; i < retries; i++) {
    try {
      return await fetch(url);
    } catch (error) {
      if (i === retries - 1) throw error;
      await delay(1000 * Math.pow(2, i)); // Exponential backoff
    }
  }
  throw new Error('Max retries exceeded');
}
```

## User-Facing Error Messages

### Guidelines
- Be helpful, not technical
- Suggest actions when possible
- Never expose internal details
- Maintain consistent tone

### Examples

```typescript
// BAD: Technical jargon
"Error: ECONNREFUSED 127.0.0.1:5432"

// GOOD: User-friendly
"Unable to save your changes. Please try again in a moment."

// BAD: Blame the user
"Invalid input in field email"

// GOOD: Helpful guidance
"Please enter a valid email address (e.g., [email protected])"
```

## Logging Standards

### What to Log
- Error message and code
- Stack trace (in development)
- Request context (sanitized)
- User action that triggered error
- Timestamp

### What NOT to Log
- Passwords or tokens
- Personal identifiable information (PII)
- Credit card numbers
- API keys or secrets

### Log Levels
- **ERROR**: Failures requiring immediate attention
- **WARN**: Potential issues or degraded functionality
- **INFO**: Important business events
- **DEBUG**: Detailed diagnostic information

## API Error Responses

```typescript
// Consistent error response format
interface ErrorResponse {
  error: {
    code: string;
    message: string;
    details?: Record<string, string[]>;
  };
  requestId?: string;
}

// Example response
{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Invalid request data",
    "details": {
      "email": ["Must be a valid email address"],
      "password": ["Must be at least 8 characters"]
    }
  },
  "requestId": "req_abc123"
}
```

## Recovery Strategies

1. **Retry with backoff**: For transient failures
2. **Circuit breaker**: Prevent cascade failures
3. **Fallback data**: Use cached or default values
4. **Graceful degradation**: Disable non-critical features
5. **User notification**: Inform and provide alternatives
Key Capabilities

What this rule helps you achieve

Consistent error patternsUser-friendly messagesProper loggingRecovery strategies
Tags
error-handlingexceptionsloggingdebugging