🎯

error-handling

🎯Skill

from dadbodgeoff/drift

VibeIndex|
What it does

Defines a comprehensive error handling framework with custom error classes, structured responses, and consistent error management across applications.

πŸ“¦

Part of

dadbodgeoff/drift(69 items)

error-handling

Installation

npm installInstall npm package
npm install -g driftdetect
npm installInstall npm package
npm install -g driftdetect@latest
npm installInstall npm package
npm install -g driftdetect-mcp
Claude Desktop ConfigurationAdd this to your claude_desktop_config.json
{ "mcpServers": { "drift": { "command": "driftdetect-mcp" } } ...
πŸ“– Extracted from docs: dadbodgeoff/drift
5Installs
-
AddedFeb 4, 2026

Skill Details

SKILL.md

Implement consistent error handling with custom error classes, error boundaries, and structured error responses. Covers logging, monitoring, and user-friendly messages.

Overview

# Error Handling

Handle errors gracefully and consistently across your application.

When to Use This Skill

  • API error responses
  • Database errors
  • External service failures
  • Validation errors
  • Authentication/authorization errors

Error Response Format

```json

{

"error": {

"code": "RESOURCE_NOT_FOUND",

"message": "User not found",

"details": { "userId": "123" },

"requestId": "req_abc123"

}

}

```

TypeScript Implementation

Custom Error Classes

```typescript

// errors/app-error.ts

export class AppError extends Error {

constructor(

public code: string,

public message: string,

public statusCode: number = 500,

public details?: Record,

public isOperational: boolean = true

) {

super(message);

this.name = 'AppError';

Error.captureStackTrace(this, this.constructor);

}

}

// Common error types

export class NotFoundError extends AppError {

constructor(resource: string, id?: string) {

super(

'RESOURCE_NOT_FOUND',

${resource} not found,

404,

id ? { [${resource.toLowerCase()}Id]: id } : undefined

);

}

}

export class ValidationError extends AppError {

constructor(details: Array<{ field: string; message: string }>) {

super('VALIDATION_ERROR', 'Validation failed', 400, { errors: details });

}

}

export class UnauthorizedError extends AppError {

constructor(message = 'Authentication required') {

super('UNAUTHORIZED', message, 401);

}

}

export class ForbiddenError extends AppError {

constructor(message = 'Access denied') {

super('FORBIDDEN', message, 403);

}

}

export class ConflictError extends AppError {

constructor(message: string, details?: Record) {

super('CONFLICT', message, 409, details);

}

}

export class RateLimitError extends AppError {

constructor(retryAfter: number) {

super('RATE_LIMITED', 'Too many requests', 429, { retryAfter });

}

}

export class ExternalServiceError extends AppError {

constructor(service: string, originalError?: Error) {

super(

'EXTERNAL_SERVICE_ERROR',

${service} service unavailable,

503,

{ service, originalMessage: originalError?.message }

);

}

}

```

Error Handler Middleware

```typescript

// middleware/error-handler.ts

import { Request, Response, NextFunction } from 'express';

import { AppError } from '../errors/app-error';

import { logger } from '../utils/logger';

interface ErrorResponse {

error: {

code: string;

message: string;

details?: Record;

requestId?: string;

};

}

export function errorHandler(

err: Error,

req: Request,

res: Response,

next: NextFunction

) {

const requestId = req.headers['x-request-id'] as string;

// Handle known operational errors

if (err instanceof AppError) {

logger.warn('Operational error', {

code: err.code,

message: err.message,

statusCode: err.statusCode,

requestId,

path: req.path,

});

const response: ErrorResponse = {

error: {

code: err.code,

message: err.message,

details: err.details,

requestId,

},

};

return res.status(err.statusCode).json(response);

}

// Handle Prisma errors

if (err.name === 'PrismaClientKnownRequestError') {

const prismaError = err as any;

if (prismaError.code === 'P2002') {

return res.status(409).json({

error: {

code: 'DUPLICATE_ENTRY',

message: 'Resource already exists',

details: { fields: prismaError.meta?.target },

requestId,

},

});

}

if (prismaError.code === 'P2025') {

return res.status(404).json({

error: {

code: 'RESOURCE_NOT_FOUND',

message: 'Resource not found',

requestId,

},

});

}

}

// Handle unknown errors (programming errors)

logger.error('Unhandled error', {

error: err.message,

stack: err.stack,

requestId,

path: req.path,

});

// Don't leak error details in production

const message = process.env.NODE_ENV === 'production'

? 'Internal server error'

: err.message;

return res.status(500).json({

error: {

code: 'INTERNAL_ERROR',

message,

requestId,

},

});

}

```

Async Handler Wrapper

```typescript

// utils/async-handler.ts

import { Request, Response, NextFunction, RequestHandler } from 'express';

type AsyncRequestHandler = (

req: Request,

res: Response,

next: NextFunction

) => Promise;

export function asyncHandler(fn: AsyncRequestHandler): RequestHandler {

return (req, res, next) => {

Promise.resolve(fn(req, res, next)).catch(next);

};

}

// Usage

router.get('/users/:id', asyncHandler(async (req, res) => {

const user = await userService.findById(req.params.id);

if (!user) {

throw new NotFoundError('User', req.params.id);

}

res.json(user);

}));

```

Service Layer Error Handling

```typescript

// services/user-service.ts

import { NotFoundError, ConflictError } from '../errors/app-error';

class UserService {

async findById(id: string): Promise {

const user = await db.users.findUnique({ where: { id } });

if (!user) {

throw new NotFoundError('User', id);

}

return user;

}

async create(data: CreateUserInput): Promise {

const existing = await db.users.findUnique({ where: { email: data.email } });

if (existing) {

throw new ConflictError('Email already registered', { email: data.email });

}

return db.users.create({ data });

}

async updateEmail(userId: string, newEmail: string): Promise {

try {

return await db.users.update({

where: { id: userId },

data: { email: newEmail },

});

} catch (error) {

if (error.code === 'P2002') {

throw new ConflictError('Email already in use');

}

throw error;

}

}

}

```

Python Implementation

```python

# errors/app_error.py

from dataclasses import dataclass

from typing import Optional, Any

@dataclass

class AppError(Exception):

code: str

message: str

status_code: int = 500

details: Optional[dict[str, Any]] = None

class NotFoundError(AppError):

def __init__(self, resource: str, id: str = None):

super().__init__(

code="RESOURCE_NOT_FOUND",

message=f"{resource} not found",

status_code=404,

details={f"{resource.lower()}_id": id} if id else None,

)

class ValidationError(AppError):

def __init__(self, errors: list[dict]):

super().__init__(

code="VALIDATION_ERROR",

message="Validation failed",

status_code=400,

details={"errors": errors},

)

class UnauthorizedError(AppError):

def __init__(self, message: str = "Authentication required"):

super().__init__(code="UNAUTHORIZED", message=message, status_code=401)

class ForbiddenError(AppError):

def __init__(self, message: str = "Access denied"):

super().__init__(code="FORBIDDEN", message=message, status_code=403)

```

FastAPI Error Handler

```python

# middleware/error_handler.py

from fastapi import Request, HTTPException

from fastapi.responses import JSONResponse

from errors.app_error import AppError

async def app_error_handler(request: Request, exc: AppError):

return JSONResponse(

status_code=exc.status_code,

content={

"error": {

"code": exc.code,

"message": exc.message,

"details": exc.details,

"requestId": request.headers.get("x-request-id"),

}

},

)

# Register in app

app.add_exception_handler(AppError, app_error_handler)

```

Frontend Error Handling

```typescript

// api-client.ts

class ApiError extends Error {

constructor(

public code: string,

public message: string,

public statusCode: number,

public details?: Record

) {

super(message);

}

}

async function apiRequest(url: string, options?: RequestInit): Promise {

const response = await fetch(url, options);

if (!response.ok) {

const body = await response.json();

throw new ApiError(

body.error.code,

body.error.message,

response.status,

body.error.details

);

}

return response.json();

}

// Usage with error handling

try {

const user = await apiRequest('/api/users/123');

} catch (error) {

if (error instanceof ApiError) {

if (error.code === 'RESOURCE_NOT_FOUND') {

showNotification('User not found');

} else if (error.code === 'VALIDATION_ERROR') {

showFormErrors(error.details.errors);

}

}

}

```

Best Practices

  1. Use error codes - Machine-readable, stable across versions
  2. Include request ID - Essential for debugging
  3. Log appropriately - Warn for operational, error for bugs
  4. Don't leak internals - Hide stack traces in production
  5. Be consistent - Same format everywhere

Common Mistakes

  • Returning stack traces to users
  • Generic "Something went wrong" messages
  • Not logging errors
  • Inconsistent error formats
  • Catching and swallowing errors

More from this repository10

🎯
feature-flags🎯Skill

Enables controlled feature rollouts, A/B testing, and selective feature access through configurable flags for gradual deployment and user targeting.

🎯
design-tokens🎯Skill

Generates a comprehensive, type-safe design token system with WCAG AA color compliance and multi-framework support for consistent visual design.

🎯
file-uploads🎯Skill

Securely validates, scans, and processes file uploads with multi-stage checks, malware detection, and race condition prevention.

🎯
ai-coaching🎯Skill

Guides users through articulating creative intent by extracting structured parameters and detecting conversation readiness.

🎯
environment-config🎯Skill

Validates and centralizes environment variables with type safety, fail-fast startup checks, and multi-environment support.

🎯
community-feed🎯Skill

Generates efficient social feed with cursor pagination, trending algorithms, and engagement tracking for infinite scroll experiences.

🎯
cloud-storage🎯Skill

Enables secure, multi-tenant cloud file storage with signed URLs, direct uploads, and visibility control for user-uploaded assets.

🎯
email-service🎯Skill

Simplifies email sending, templating, and tracking with robust SMTP integration and support for multiple email providers and transactional workflows.

🎯
error-sanitization🎯Skill

Sanitizes error messages by logging full details server-side while exposing only generic, safe messages to prevent sensitive information leakage.

🎯
batch-processing🎯Skill

Optimizes database operations by collecting and batching independent records, improving throughput by 30-40% with built-in fallback processing.