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
Error Code: VALIDATION_ERROR
Class: ValidationError
Default Message: "message"
Example Response:
{
"code": "VALIDATION_ERROR",
"message": "message"
}401
Error Code: UNAUTHORIZED
Class: UnauthorizedError
Default Message: "message"
Example Response:
{
"code": "UNAUTHORIZED",
"message": "message"
}402
Error Code: QUOTA_EXCEEDED
Class: QuotaExceededError
Default Message: "message"
Example Response:
{
"code": "QUOTA_EXCEEDED",
"message": "message"
}403
Error Code: FORBIDDEN
Class: ForbiddenError
Default Message: "message"
Example Response:
{
"code": "FORBIDDEN",
"message": "message"
}404
Error Code: NOT_FOUND
Class: NotFoundError
Default Message: "message"
Example Response:
{
"code": "NOT_FOUND",
"message": "message"
}409
Error Code: CONFLICT
Class: ConflictError
Default Message: "message"
Example Response:
{
"code": "CONFLICT",
"message": "message"
}429
Error Code: RATE_LIMIT_EXCEEDED
Class: RateLimitError
Default Message: "message"
Example Response:
{
"code": "RATE_LIMIT_EXCEEDED",
"message": "message"
}500
Error Code: INTERNAL_ERROR
Class: InternalError
Default Message: "message"
Example Response:
{
"code": "INTERNAL_ERROR",
"message": "message"
}503
Error Code: SERVICE_UNAVAILABLE
Class: ServiceUnavailableError
Default Message: "message"
Example Response:
{
"code": "SERVICE_UNAVAILABLE",
"message": "message"
}Quick Reference
| Status | Code | Description |
|---|---|---|
| 400 | VALIDATION_ERROR | |
| 401 | UNAUTHORIZED | |
| 402 | QUOTA_EXCEEDED | |
| 403 | FORBIDDEN | |
| 404 | NOT_FOUND | |
| 409 | CONFLICT | |
| 429 | RATE_LIMIT_EXCEEDED | |
| 500 | INTERNAL_ERROR | |
| 503 | SERVICE_UNAVAILABLE |
Error Codes
9 error types defined
Auto-generated from api/src/lib/errors.ts. Run pnpm docs:gen to update.