Error Handling
Pixelflare uses a centralised error handling system with type-safe error classes and consistent error responses across both the API and frontend.
API Error Handling
Error Classes
All API errors extend from the base ApiError class, which provides:
- Type safety - Each error class has a specific HTTP status code and error code
- Structured logging - Errors include message, code, status, and optional details
- Operational flag - Distinguishes expected errors from unexpected crashes
Available error classes:
| Class | Status | Code | Use Case |
|---|---|---|---|
ValidationError | 400 | VALIDATION_ERROR | Invalid request data |
UnauthorizedError | 401 | UNAUTHORIZED | Missing/invalid authentication |
ForbiddenError | 403 | FORBIDDEN | Insufficient permissions |
NotFoundError | 404 | NOT_FOUND | Resource doesn't exist |
ConflictError | 409 | CONFLICT | Duplicate resource |
RateLimitError | 429 | RATE_LIMIT_EXCEEDED | Too many requests |
QuotaExceededError | 402 | QUOTA_EXCEEDED | Usage limit reached |
ServiceUnavailableError | 503 | SERVICE_UNAVAILABLE | Service temporarily down |
InternalError | 500 | INTERNAL_ERROR | Unexpected server error |
Usage in Routes
import { NotFoundError, ValidationError } from '@/lib/errors';
// Throw specific errors
if (!image) {
throw new NotFoundError('Image not found');
}
// Add context with details
throw new ValidationError('Invalid dimensions', {
width: requestedWidth,
maxWidth: MAX_WIDTH,
});Error Handler Middleware
The error-handler.ts middleware automatically catches all errors and formats responses consistently:
{
"success": false,
"error": {
"code": "NOT_FOUND",
"message": "Image not found",
"details": { ... }
}
}Features:
- Catches all thrown errors including Zod validation errors
- Logs errors appropriately (warnings for 4xx, errors for 5xx)
- Prevents stack traces leaking to clients
- Consistent JSON response format
Best Practices
Do:
- Throw specific error classes for known failure cases
- Include relevant context in
detailsfor debugging - Use
ValidationErrorfor input validation failures - Let the error handler format responses
Don't:
- Return raw
c.json({ error: ... })responses - Expose internal details (database errors, file paths) to clients
- Use generic
Errorfor expected failures - Log sensitive data in error details
Frontend Error Handling
Error Utilities
The errors.ts utility provides type-safe error handling:
import { handleError, getUserMessage, toAppError } from '$lib/utils/errors';
// Convert any error to AppError
const appError = toAppError(error);
// Log and handle errors
const appError = handleError(error, {
operation: 'uploadImage',
component: 'ImageUploader',
});
// Get user-friendly message (sanitised for production)
const message = getUserMessage(error);Error Pages
SvelteKit's +error.svelte pages handle routing errors:
- 404 errors - Show helpful suggestions and navigation
- 500+ errors - Display generic message, hide technical details
- Custom layouts - Route-specific error pages in nested routes
Usage in Components
import { handleError, getUserMessage } from '$lib/utils/errors';
async function uploadImage() {
try {
await api.post('/images', formData);
} catch (error) {
// Log error and get sanitised message
const appError = handleError(error, {
operation: 'uploadImage',
});
errorMessage = getUserMessage(appError);
}
}Best Practices
Do:
- Always use
handleError()for logging and context - Display user-friendly messages via
getUserMessage() - Catch errors at component boundaries
- Provide actionable error messages ("Image too large" not "Validation failed")
Don't:
- Show raw error messages to users (stack traces, internal errors)
- Ignore errors silently
- Use
console.errordirectly (use logger utilities) - Display sensitive information in production
Error Response Format
All API errors follow this structure:
{
success: false,
error: {
code: string, // Machine-readable error code
message: string, // Human-readable description
details?: object // Optional context (validation errors, etc.)
}
}Error Code Reference
Complete reference of all API error codes.
HTTP Status Codes
400 400 - Validation or bad request error
Error Code: VALIDATION_ERROR
Class: ValidationError
Default Message: "message"
Example Response:
{
"code": "VALIDATION_ERROR",
"message": "message"
}401 401 - Authentication error
Error Code: UNAUTHORIZED
Class: UnauthorizedError
Default Message: "message"
Example Response:
{
"code": "UNAUTHORIZED",
"message": "message"
}402 402 - Quota exceeded (usage limit)
Error Code: QUOTA_EXCEEDED
Class: QuotaExceededError
Default Message: "message"
Example Response:
{
"code": "QUOTA_EXCEEDED",
"message": "message"
}403 403 - Permission error
Error Code: FORBIDDEN
Class: ForbiddenError
Default Message: "message"
Example Response:
{
"code": "FORBIDDEN",
"message": "message"
}404 404 - Resource not found
Error Code: NOT_FOUND
Class: NotFoundError
Default Message: "message"
Example Response:
{
"code": "NOT_FOUND",
"message": "message"
}409 409 - Resource conflict (e.g., duplicate)
Error Code: CONFLICT
Class: ConflictError
Default Message: "message"
Example Response:
{
"code": "CONFLICT",
"message": "message"
}429 429 - Rate limit exceeded
Error Code: RATE_LIMIT_EXCEEDED
Class: RateLimitError
Default Message: "message"
Example Response:
{
"code": "RATE_LIMIT_EXCEEDED",
"message": "message"
}500 500 - Internal server error
Error Code: INTERNAL_ERROR
Class: InternalError
Default Message: "message"
Example Response:
{
"code": "INTERNAL_ERROR",
"message": "message"
}503 503 - Service unavailable
Error Code: SERVICE_UNAVAILABLE
Class: ServiceUnavailableError
Default Message: "message"
Example Response:
{
"code": "SERVICE_UNAVAILABLE",
"message": "message"
}Quick Reference
| Status | Code | Description |
|---|---|---|
| 400 | VALIDATION_ERROR | 400 - Validation or bad request error |
| 401 | UNAUTHORIZED | 401 - Authentication error |
| 402 | QUOTA_EXCEEDED | 402 - Quota exceeded (usage limit) |
| 403 | FORBIDDEN | 403 - Permission error |
| 404 | NOT_FOUND | 404 - Resource not found |
| 409 | CONFLICT | 409 - Resource conflict (e.g., duplicate) |
| 429 | RATE_LIMIT_EXCEEDED | 429 - Rate limit exceeded |
| 500 | INTERNAL_ERROR | 500 - Internal server error |
| 503 | SERVICE_UNAVAILABLE | 503 - Service unavailable |
Error Codes
9 error types defined
Auto-generated from api/src/lib/errors.ts. Run pnpm docs:gen to update.