# Error Handling Lockness provides a comprehensive error handling system with automatic discovery, elegant error pages, and clean console output. ## 🎯 Overview The framework handles errors through three layers: 1. **Auto-Discovery**: Automatically detects custom error handlers 2. **Error Formatting**: Clean, color-coded console output 3. **Default Pages**: Built-in error pages with no dependencies ## 🔍 Auto-Discovery Lockness automatically discovers custom error handlers without requiring manual registration in your kernel. This eliminates boilerplate and follows the zero-configuration philosophy. **How it works:** When your application starts, `@lockness/core` checks for a custom error handler at: ``` app/view/pages/errors/error_handler.tsx ``` If found, it's used automatically. If not, the framework uses its built-in default error handler. **Benefits:** - ✅ No imports needed in `kernel.tsx` - ✅ No manual registration with `useErrorHandler()` - ✅ Convention over configuration - ✅ Automatic fallback to defaults ## 🎨 Creating Custom Error Pages Generate custom error pages using the CLI: ```bash deno task cli make:error-pages ``` This creates: ``` app/view/pages/errors/ ├── error_handler.tsx # Main error handler (auto-discovered) ├── not_found.tsx # 404 page ├── unauthorized.tsx # 401 page ├── forbidden.tsx # 403 page └── server_error.tsx # 500 page ``` **Generated templates use:** - Inline CSS (no framework dependencies) - System fonts (no external font loading) - Responsive design - Clean, professional styling ## 📝 Custom Error Handler Example of a custom error handler: ```typescript // app/view/pages/errors/error_handler.tsx import { Context, formatErrorForConsole, HTTPException } from '@lockness/core' import { NotFoundPage } from './not_found.tsx' import { UnauthorizedPage } from './unauthorized.tsx' import { ForbiddenPage } from './forbidden.tsx' import { ServerErrorPage } from './server_error.tsx' export function errorHandler(error: Error, c: Context) { const status = error instanceof HTTPException ? error.status : 500 const path = c.req.path // Use centralized error formatter for clean console output formatErrorForConsole(error, status, path, { showStackTrace: status >= 500, }) // Return appropriate error page if (error instanceof HTTPException) { switch (status) { case 404: return c.html(, 404) case 401: return c.html(, 401) case 403: return c.html(, 403) default: return c.html(, status) } } return c.html(, 500) } ``` ## 🖥️ Error Console Formatting The `formatErrorForConsole()` utility provides clean, color-coded console output: ```typescript import { formatErrorForConsole } from '@lockness/core' formatErrorForConsole(error, status, path, { showStackTrace: status >= 500, // Show trace for server errors }) ``` **Output Examples:** **404 Not Found** (minimal): ``` ⚠️ 404 Not Found: /api/users/999 ``` **401 Unauthorized** (simple): ``` 🔒 401 Unauthorized: /admin/dashboard ``` **500 Internal Server Error** (detailed): ``` ❌ 500 Internal Server Error: /api/users Error: Database connection failed at UserRepository.findAll (file:///app/repository/user_repository.ts:42:15) at UserService.getUsers (file:///app/service/user_service.ts:18:30) ``` **Benefits:** - ✅ Color-coded by severity (warning, error, critical) - ✅ Minimal output for expected errors (404) - ✅ Full stack traces for server errors (500+) - ✅ Consistent formatting across the application ## 🎨 Custom Error Pages ### 404 Not Found Page ```typescript // app/view/pages/errors/not_found.tsx export function NotFoundPage() { return ( 404 - Page Not Found

404

Page not found

Go Home
) } ``` ### API Error Responses For API endpoints, return JSON error responses: ```typescript @Controller('/api') export class ApiController { @Get('/users/:id') async show(c: Context) { const id = c.req.param('id') const user = await this.userService.findById(id) if (!user) { return c.json({ success: false, error: 'User not found', code: 'USER_NOT_FOUND', }, 404) } return c.json({ success: true, data: user }) } } ``` ## 🚀 Default Error Handler If you don't create custom error pages, Lockness provides elegant default pages: **Features:** - Clean, responsive design - Inline CSS (no external dependencies) - System fonts (zero external requests) - Appropriate HTTP status codes - User-friendly error messages **Default pages include:** - 404 Not Found - 401 Unauthorized - 403 Forbidden - 500 Internal Server Error ## 🎭 HTTP Exceptions Throw HTTP exceptions from anywhere in your code: ```typescript import { HTTPException } from '@lockness/core' // 404 Not Found throw new HTTPException(404, { message: 'User not found' }) // 401 Unauthorized throw new HTTPException(401, { message: 'Invalid credentials' }) // 403 Forbidden throw new HTTPException(403, { message: 'Access denied' }) // 500 Internal Server Error throw new HTTPException(500, { message: 'Database connection failed' }) ``` ## 🔧 Advanced Usage ### Custom Error Types Create custom error classes for domain-specific errors: ```typescript export class ValidationError extends Error { constructor(public fields: Record) { super('Validation failed') this.name = 'ValidationError' } } // In error handler if (error instanceof ValidationError) { return c.json({ success: false, errors: error.fields, }, 422) } ``` ### Error Logging Integrate with external logging services: ```typescript import { formatErrorForConsole } from '@lockness/core' export function errorHandler(error: Error, c: Context) { const status = error instanceof HTTPException ? error.status : 500 // Console output formatErrorForConsole(error, status, c.req.path) // External logging (e.g., Sentry) if (status >= 500) { Sentry.captureException(error) } return c.html(, status) } ``` ### Development vs Production Show different error details based on environment: ```typescript export function errorHandler(error: Error, c: Context) { const status = error instanceof HTTPException ? error.status : 500 const isDev = Deno.env.get('APP_ENV') === 'development' formatErrorForConsole(error, status, c.req.path) return c.html( , status, ) } ``` ## 📚 Best Practices ### 1. Use HTTP Exceptions Prefer throwing `HTTPException` over returning error responses: ```typescript // ✅ Good if (!user) { throw new HTTPException(404, { message: 'User not found' }) } // ❌ Avoid if (!user) { return c.json({ error: 'User not found' }, 404) } ``` ### 2. Consistent Error Format Use a consistent format for API errors: ```typescript interface ErrorResponse { success: false error: string code?: string details?: unknown } ``` ### 3. Appropriate Status Codes Use correct HTTP status codes: - **404**: Resource not found - **401**: Authentication required - **403**: Authenticated but not authorized - **422**: Validation failed - **500**: Server error ### 4. Clean Console Output Let `formatErrorForConsole()` handle console logging: ```typescript // ✅ Good formatErrorForConsole(error, status, path) // ❌ Avoid console.error('Error:', error) console.error(error.stack) ``` ### 5. Framework-Agnostic Templates Keep error pages framework-agnostic with inline CSS: ```typescript // ✅ Good - Inline CSS // ❌ Avoid - External framework ``` ## 🔍 Troubleshooting ### Error Handler Not Found **Symptom:** Custom error pages not displaying **Solution:** Ensure file exists at correct path: ``` app/view/pages/errors/error_handler.tsx ``` ### Stack Traces in Production **Symptom:** Full error details visible to users **Solution:** Check `showStackTrace` option: ```typescript formatErrorForConsole(error, status, path, { showStackTrace: status >= 500 && Deno.env.get('APP_ENV') === 'development', }) ``` ### CSS Not Loading on Error Pages **Symptom:** Unstyled error pages **Solution:** Use inline CSS in error page components (already done by default in generated templates). ## 📚 Next Steps - [Learn about Validation](https://lockness.land/docs/validation) - [Configure Logging](https://lockness.land/docs/logging) - [Deploy to Production](https://lockness.land/docs/deployment)