Skip to content

Instantly share code, notes, and snippets.

@theskillwithin
Created February 1, 2026 02:18
Show Gist options
  • Select an option

  • Save theskillwithin/1326ad5829e5b980f85c6036d3935f33 to your computer and use it in GitHub Desktop.

Select an option

Save theskillwithin/1326ad5829e5b980f85c6036d3935f33 to your computer and use it in GitHub Desktop.
import { data } from 'react-router';
export class AppError extends Error {
constructor(
message: string,
public statusCode: number = 500,
public code?: string
) {
super(message);
this.name = 'AppError';
}
}
export class ValidationError extends AppError {
constructor(
message: string,
public fieldErrors: Record<string, string[]> = {}
) {
super(message, 400, 'VALIDATION_ERROR');
this.name = 'ValidationError';
}
}
export class NotFoundError extends AppError {
constructor(message = 'Not found') {
super(message, 404, 'NOT_FOUND');
this.name = 'NotFoundError';
}
}
type HandlerFn<T> = (args: LoaderFunctionArgs | ActionFunctionArgs) => Promise<T>;
export function withErrorHandling<T>(handler: HandlerFn<T>) {
return async (args: LoaderFunctionArgs | ActionFunctionArgs) => {
try {
return await handler(args);
} catch (error) {
if (error instanceof ValidationError) {
return data(
{ error: error.message, fieldErrors: error.fieldErrors },
{ status: 400 }
);
}
if (error instanceof NotFoundError) {
throw new Response(error.message, { status: 404 });
}
if (error instanceof AppError) {
return data(
{ error: error.message, code: error.code },
{ status: error.statusCode }
);
}
// Unknown error - let it bubble to error boundary
console.error('Unexpected error:', error);
throw error;
}
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment