Description
Current State
API routes return inconsistent error shapes:
// Different patterns found:
{ error: 'message' }
{ error: 'message', details: [...] }
{ error: 'message', status: 500 }
{ message: 'error' } // Some routes use 'message' instead
Status codes are also inconsistent — some routes return 500 for everything, others properly use 400/401/403/404.
Desired Outcome
- Create typed error classes:
// lib/api/errors.ts
export class ApiError extends Error {
constructor(
message: string,
public statusCode: number,
public code: string,
public details?: Record<string, unknown>
) { super(message); }
}
export class ValidationError extends ApiError {
constructor(message: string, details?: ZodError) {
super(message, 400, 'VALIDATION_ERROR', details);
}
}
export class AuthenticationError extends ApiError {
constructor(message = 'Unauthorized') {
super(message, 401, 'AUTHENTICATION_ERROR');
}
}
export class ForbiddenError extends ApiError {
constructor(message = 'Forbidden') {
super(message, 403, 'FORBIDDEN');
}
}
- Create error handler:
// lib/api/error-handler.ts
export function handleApiError(error: unknown): NextResponse {
if (error instanceof ApiError) {
return NextResponse.json(
{ error: error.message, code: error.code, details: error.details },
{ status: error.statusCode }
);
}
logger.error('Unhandled error', error);
return NextResponse.json(
{ error: 'Internal server error', code: 'INTERNAL_ERROR' },
{ status: 500 }
);
}
- Standardize response format:
interface ApiErrorResponse {
error: string;
code: string;
details?: Record<string, unknown>;
}
How to get started
- Create
lib/api/errors.ts with error classes
- Create
lib/api/error-handler.ts with handler function
- Migrate
app/api/accounts/route.ts as proof of concept
- Document the pattern in
docs/api/ERROR_HANDLING.md
Acceptance Criteria
Description
Current State
API routes return inconsistent error shapes:
Status codes are also inconsistent — some routes return 500 for everything, others properly use 400/401/403/404.
Desired Outcome
How to get started
lib/api/errors.tswith error classeslib/api/error-handler.tswith handler functionapp/api/accounts/route.tsas proof of conceptdocs/api/ERROR_HANDLING.mdAcceptance Criteria
lib/api/errors.tswith 4+ error classeslib/api/error-handler.tswith unified handler