Agent skill
error-handling-vassovass-scl-v3
Stars
163
Forks
31
Install this agent skill to your Project
npx add-skill https://github.com/majiayu000/claude-skill-registry/tree/main/skills/development/error-handling-vassovass-scl-v3
SKILL.md
Error Handling Skill
Overview
StepLeague uses a centralized error handling system in src/lib/errors.ts.
Key Components:
AppError- Typed error class with codes and contextErrorCode- Enum of all error typesnormalizeError()- Convert any error to AppErrorreportError()/reportErrorClient()- Log and report errors
Throwing Errors
Use AppError with Specific Codes
typescript
import { AppError, ErrorCode } from "@/lib/errors";
throw new AppError({
code: ErrorCode.UPLOAD_TOO_LARGE,
message: "File exceeds 5MB limit",
context: { fileSize: file.size, maxSize: MAX_SIZE },
recoverable: true, // Can user retry?
});
AppError Options
| Option | Type | Description |
|---|---|---|
code |
ErrorCode |
Required. Error type for programmatic handling |
message |
string |
Required. Human-readable description |
context |
object |
Additional debug info |
cause |
Error |
Original error that caused this |
recoverable |
boolean |
Can user retry? Default: true |
Available Error Codes
Upload/Attachment Errors
UPLOAD_FAILED- General upload failureUPLOAD_TOO_LARGE- File size limit exceededUPLOAD_INVALID_TYPE- Wrong file typeUPLOAD_INVALID_FORMAT- Invalid file formatUPLOAD_PROCESSING_FAILED- Image processing failedUPLOAD_STORAGE_ERROR- Storage service errorATTACHMENT_NOT_FOUND- Attachment doesn't existATTACHMENT_FETCH_FAILED- Failed to retrieve attachmentATTACHMENT_DELETE_FAILED- Failed to delete attachment
API Errors
API_REQUEST_FAILED- General API failureAPI_FETCH_FAILED- Network fetch failedAPI_VALIDATION_ERROR- Request validation failedAPI_UNAUTHORIZED- Not authenticated (401)API_FORBIDDEN- Not authorized (403)API_NOT_FOUND- Resource not found (404)
Database Errors
DB_INSERT_FAILED- Insert operation failedDB_UPDATE_FAILED- Update operation failedDB_DELETE_FAILED- Delete operation failedDB_QUERY_FAILED- Select query failed
Menu Errors
MENU_NOT_FOUND- Menu doesn't existMENU_CREATE_FAILED- Failed to create menuMENU_ITEM_NOT_FOUND- Menu item doesn't existMENU_ITEM_CREATE_FAILED- Failed to create itemMENU_ITEM_UPDATE_FAILED- Failed to update itemMENU_ITEM_DELETE_FAILED- Failed to delete itemMENU_BATCH_UPDATE_FAILED- Failed to reorder itemsMENU_INVALID_HIERARCHY- Invalid parent/child structure
Form/Validation Errors
VALIDATION_FAILED- General validation failureREQUIRED_FIELD_MISSING- Required field is empty
Network Errors
NETWORK_ERROR- No network connectionTIMEOUT_ERROR- Request timed outREQUEST_TIMEOUT- Operation timed outRATE_LIMIT_EXCEEDED- Too many requests
Fallback
UNKNOWN_ERROR- Catch-all for unexpected errors
Catching & Reporting Errors
Standard Pattern
typescript
import { normalizeError, reportErrorClient, ErrorCode } from "@/lib/errors";
import { toast } from "@/hooks/use-toast";
try {
await doSomething();
} catch (err) {
// 1. Normalize to AppError
const appError = normalizeError(err, ErrorCode.API_REQUEST_FAILED);
// 2. Report (logs to console, future: Sentry)
reportErrorClient(appError);
// 3. Show user-friendly message
toast({
title: "Error",
description: appError.toUserMessage(),
variant: "destructive",
});
}
User-Friendly Messages
appError.toUserMessage() converts technical errors to friendly text:
| Code | User Message |
|---|---|
UPLOAD_TOO_LARGE |
"The file is too large. Please choose a smaller file." |
NETWORK_ERROR |
"Connection lost. Please check your internet and try again." |
API_UNAUTHORIZED |
"Please sign in to continue." |
API_FORBIDDEN |
"You don't have permission to do this." |
Creating Errors from API Responses
typescript
import { errorFromResponse } from "@/lib/errors";
const response = await fetch("/api/something");
if (!response.ok) {
const appError = await errorFromResponse(response, "Failed to save");
throw appError;
}
This automatically:
- Extracts error message from JSON body
- Maps HTTP status to ErrorCode
- Sets
recoverablebased on status (5xx = retryable)
Server-Side Error Reporting
typescript
import { reportError } from "@/lib/errors";
// In API route
try {
await doServerThing();
} catch (error) {
await reportError(error, user?.id, requestId);
return serverError("Operation failed");
}
Server-side reporting uses @/lib/server/logger for Vercel logs.
Best Practices
1. Always Normalize Unknown Errors
typescript
// ✅ Normalize any caught error
const appError = normalizeError(err, ErrorCode.UNKNOWN_ERROR);
// ❌ Don't assume error type
console.log(err.message); // May not be an Error!
2. Provide Context for Debugging
typescript
throw new AppError({
code: ErrorCode.UPLOAD_FAILED,
message: "Failed to upload image",
context: {
filename: file.name,
size: file.size,
type: file.type,
userId: user.id,
},
});
3. Chain Errors with Cause
typescript
try {
await uploadToStorage(file);
} catch (cause) {
throw new AppError({
code: ErrorCode.UPLOAD_STORAGE_ERROR,
message: "Storage upload failed",
cause: cause instanceof Error ? cause : undefined,
});
}
4. Use recoverable Flag
typescript
// User can retry
throw new AppError({
code: ErrorCode.NETWORK_ERROR,
message: "Request failed",
recoverable: true, // Show "Try Again" button
});
// User cannot recover
throw new AppError({
code: ErrorCode.API_FORBIDDEN,
message: "Access denied",
recoverable: false, // Show "Contact Support"
});
Adding New Error Codes
When adding new features that need specific error handling:
- Add to ErrorCode enum in
src/lib/errors.ts:
typescript
export enum ErrorCode {
// ... existing codes
// New feature errors
MY_FEATURE_FAILED = 'MY_FEATURE_FAILED',
MY_FEATURE_INVALID = 'MY_FEATURE_INVALID',
}
- Add user-friendly message in
toUserMessage():
typescript
const friendlyMessages: Partial<Record<ErrorCode, string>> = {
// ... existing messages
[ErrorCode.MY_FEATURE_FAILED]: 'Unable to complete operation. Please try again.',
};
Reference Files
| File | Purpose |
|---|---|
src/lib/errors.ts |
AppError class, ErrorCode enum, utilities |
src/lib/server/logger.ts |
Server-side logging |
Related Skills
api-handler- Uses error handling for API routesarchitecture-philosophy- Error handling is key defensive pattern
Didn't find tool you were looking for?