error-handling-patterns
Error handling patterns including exceptions, Result pattern, validation strategies, retry logic, and circuit breakers. **ALWAYS use when implementing error handling in backend code, APIs, use cases, or validation logic.** Use proactively for robust error handling, recovery mechanisms, and failure scenarios. Examples - "handle errors", "Result pattern", "throw exception", "validate input", "error recovery", "retry logic", "circuit breaker", "exception hierarchy".
What this skill does
You are an expert in error handling patterns and strategies. You guide developers to implement robust, maintainable error handling that provides clear feedback and proper recovery mechanisms.
**For complete backend implementation examples using these error handling patterns (Clean Architecture layers, DI Container, Use Cases, Repositories), see `backend-engineer` skill**
## When to Engage
You should proactively assist when:
- Implementing error handling within bounded contexts
- Designing context-specific validation logic
- Creating context-specific exception types (no base classes)
- Implementing retry or recovery mechanisms per context
- User asks about error handling strategies
- Reviewing error handling without over-abstraction
## Modular Monolith Error Handling
### Context-Specific Errors (No Base Classes)
```typescript
// ❌ BAD: Base error class creates coupling
export abstract class DomainError extends Error {
// Forces all contexts to use same error structure
}
// ✅ GOOD: Each context has its own errors
// contexts/auth/domain/errors/auth-validation.error.ts
export class AuthValidationError extends Error {
constructor(message: string, public readonly field?: string) {
super(message);
this.name = "AuthValidationError";
}
}
// contexts/tax/domain/errors/tax-calculation.error.ts
export class TaxCalculationError extends Error {
constructor(message: string, public readonly ncmCode?: string) {
super(message);
this.name = "TaxCalculationError";
}
}
```
### Error Handling Rules
1. **Each context owns its errors** - No shared error classes
2. **Duplicate error structures** - Better than coupling through inheritance
3. **Context-specific metadata** - Each error has relevant context data
4. **Simple over clever** - Avoid complex error hierarchies
## Core Principles
### 1. Use Exceptions, Not Return Codes
```typescript
// ✅ Good - Use exceptions with context
export class CreateUserUseCase {
async execute(dto: CreateUserDto): Promise<User> {
if (!this.isValidEmail(dto.email)) {
throw new ValidationError("Invalid email format", {
email: dto.email,
field: "email",
});
}
try {
return await this.repository.save(user);
} catch (error) {
throw new DatabaseError("Failed to create user", {
originalError: error,
userId: user.id,
});
}
}
}
// ❌ Bad - Return codes
export class CreateUserUseCase {
async execute(dto: CreateUserDto): Promise<{
success: boolean;
user?: User;
error?: string;
}> {
if (!this.isValidEmail(dto.email)) {
return { success: false, error: "Invalid email" };
}
// Forces caller to check success flag everywhere
}
}
```
### 2. Never Return Null for Errors
```typescript
// ✅ Good - Explicit optional with undefined
export class UserService {
async findById(id: string): Promise<User | undefined> {
return this.repository.findById(id);
}
// Or throw if must exist
async getUserById(id: string): Promise<User> {
const user = await this.repository.findById(id);
if (!user) {
throw new NotFoundError(`User ${id} not found`);
}
return user;
}
}
// ❌ Bad - Returning null loses error context
export class UserService {
async findById(id: string): Promise<User | null> {
// Why null? Not found? Database error? Network error?
return null;
}
}
```
### 3. Provide Context with Exceptions
```typescript
// ✅ Good - Rich error context
export class ValidationError extends Error {
constructor(
message: string,
public readonly context: Record<string, unknown>
) {
super(message);
this.name = "ValidationError";
}
}
throw new ValidationError("Invalid email format", {
email: dto.email,
field: "email",
rule: "email-format",
attemptedAt: new Date().toISOString(),
});
// ❌ Bad - No context
throw new Error("Invalid");
```
## Exception Hierarchy
### Custom Domain Exceptions
```typescript
// Base domain exception
export abstract class DomainError extends Error {
constructor(
message: string,
public readonly code: string,
public readonly context?: Record<string, unknown>
) {
super(message);
this.name = this.constructor.name;
}
}
// Specific domain exceptions
export class UserAlreadyExistsError extends DomainError {
constructor(email: string) {
super(`User with email ${email} already exists`, "USER_ALREADY_EXISTS", {
email,
});
}
}
export class InvalidPasswordError extends DomainError {
constructor(reason: string) {
super("Password does not meet requirements", "INVALID_PASSWORD", {
reason,
});
}
}
export class InsufficientPermissionsError extends DomainError {
constructor(userId: string, resource: string, action: string) {
super(
`User ${userId} cannot ${action} ${resource}`,
"INSUFFICIENT_PERMISSIONS",
{ userId, resource, action }
);
}
}
```
### Infrastructure Exceptions
```typescript
export class DatabaseError extends Error {
constructor(
message: string,
public readonly originalError: unknown,
public readonly query?: string
) {
super(message);
this.name = "DatabaseError";
}
}
export class ExternalServiceError extends Error {
constructor(
public readonly service: string,
message: string,
public readonly statusCode?: number,
public readonly originalError?: unknown
) {
super(`${service}: ${message}`);
this.name = "ExternalServiceError";
}
}
```
## Result Pattern
For operations with expected failures:
```typescript
export type Result<T, E = Error> =
| { success: true; value: T }
| { success: false; error: E };
export class UserService {
async findByEmail(email: string): Promise<Result<User, NotFoundError>> {
const user = await this.repository.findByEmail(email);
if (!user) {
return {
success: false,
error: new NotFoundError("User not found"),
};
}
return { success: true, value: user };
}
}
// Usage
const result = await userService.findByEmail("[email protected]");
if (!result.success) {
console.error("User not found:", result.error.message);
return;
}
// TypeScript knows result.value is User here
const user = result.value;
```
### When to Use Result Pattern
**Use Result for:**
- Expected business failures (user not found, insufficient balance)
- Operations where failure is part of normal flow
- When caller needs to handle different failure types
**Use Exceptions for:**
- Unexpected errors (database connection lost, out of memory)
- Programming errors (invalid state, null pointer)
- Infrastructure failures
## Validation Patterns
### Input Validation at Boundaries
```typescript
import { z } from "zod";
// ✅ Good - Validate at system boundaries
const CreateUserSchema = z.object({
email: z.string().email("Invalid email format"),
password: z
.string()
.min(8, "Password must be at least 8 characters")
.regex(/[A-Z]/, "Password must contain uppercase letter")
.regex(/[0-9]/, "Password must contain number"),
name: z
.string()
.min(2, "Name must be at least 2 characters")
.max(100, "Name must be at most 100 characters"),
age: z
.number()
.int("Age must be an integer")
.min(18, "Must be at least 18 years old")
.optional(),
});
export type CreateUserDto = z.infer<typeof CreateUserSchema>;
// In Hono controller
import { zValidator } from "@hono/zod-validator";
app.post("/users", zValidator("json", CreateUserSchema), async (c) => {
const data = c.req.valid("json"); // Type-safe and validated
const user = await createUserUseCase.execute(data);
return c.json(user, 201);
});
```
### Domain Validation
```typescript
// ✅ Good - Validate in domain entities
export class Email {
private constructor(private readonly value: string) {}
static create(value: string): Result<Email, ValidationError> {
if (!value) {
return {
success: false,
error: new Related in Backend & APIs
jfrog
IncludedInteract with the JFrog Platform via the JFrog CLI and REST/GraphQL APIs. Use this skill when the user wants to manage Artifactory repositories, upload or download artifacts, manage builds, configure permissions, manage users and groups, work with access tokens, configure JFrog CLI servers, search artifacts, manage properties, set up replication, manage JFrog Projects, run security audits or scans, look up CVE details, query exposures scan results from JFrog Advanced Security, manage release bundles and lifecycle operations, aggregate or export platform data, or perform any JFrog Platform administration task. Also use when the user mentions jf, jfrog, artifactory, xray, distribution, evidence, apptrust, onemodel, graphql, workers, mission control, curation, advanced security, exposures, or any JFrog product name.
cupynumeric-migration-readiness
IncludedPre-migration readiness assessor for porting NumPy to cuPyNumeric. Use BEFORE substantial porting work begins when the user asks whether code will scale on GPU, whether they should migrate to cuPyNumeric, which NumPy patterns transfer cleanly, what must be refactored before porting, or mentions pre-port assessment, scaling analysis, or refactor planning. Inspect the user's source code, look up NumPy usage, cross-reference the cuPyNumeric API support manifest, and distinguish distributed-scaling-friendly patterns from blockers such as unsupported APIs, scalar synchronization, host round-trips, Python/object-heavy control flow, shape/data-dependent branching, and in-place mutation hazards. Produce a verdict of READY, LIGHT REFACTOR, SIGNIFICANT REFACTOR, or NOT RECOMMENDED, with concrete refactor pointers.
alibabacloud-data-agent-skill
IncludedInvoke Alibaba Cloud Apsara Data Agent for Analytics via CLI to perform natural language-driven data analysis on enterprise databases. Data Agent for Analytics is an intelligent data analysis agent developed by Alibaba Cloud Database team for enterprise users. It automatically completes requirement analysis, data understanding, analysis insights, and report generation based on natural language descriptions. This tool supports: discovering data resources (instances/databases/tables) managed in DMS, initiating query or deep analysis sessions, real-time progress tracking, and retrieving analysis conclusions and generated reports. Use this Skill when users need to query databases, analyze data trends, generate data reports, ask questions in natural language, or mention "Data Agent", "data analysis", "database query", "SQL analysis", "data insights".
token-optimizer
IncludedReduce OpenClaw token usage and API costs through smart model routing, heartbeat optimization, budget tracking, and native 2026.2.15 features (session pruning, bootstrap size limits, cache TTL alignment). Use when token costs are high, API rate limits are being hit, or hosting multiple agents at scale. The 4 executable scripts (context_optimizer, model_router, heartbeat_optimizer, token_tracker) are local-only — no network requests, no subprocess calls, no system modifications. Reference files (PROVIDERS.md, config-patches.json) document optional multi-provider strategies that require external API keys and network access if you choose to use them. See SECURITY.md for full breakdown.
resend-cli
IncludedUse this skill when the task is specifically about operating Resend from an AI agent, terminal session, or CI job via the official resend CLI: installing/authenticating the CLI, sending/listing/updating/cancelling emails, batch sends, domains and DNS, webhooks and local listeners, inbound receiving, contacts, topics, segments, broadcasts, templates, API keys, profiles, or debugging Resend CLI/API failures. Trigger on mentions of Resend CLI, `resend`, `resend doctor`, `resend emails send`, `resend domains`, `resend webhooks listen`, `resend emails receiving`, or agent-friendly terminal automation.
alibabacloud-odps-maxframe-coding
IncludedUse this skill for MaxFrame SDK development and documentation navigation on Alibaba Cloud MaxCompute (ODPS). Helps answer MaxFrame API, concept, official example, and supported pandas API questions; create data processing programs; read/write MaxCompute tables; debug jobs (remote or local); and build custom DPE runtime images. Trigger when users mention MaxFrame, MaxCompute with MaxFrame, ODPS table processing, DPE runtime, MaxFrame docs/examples, DataFrame/Tensor operations, or GPU runtime setup. Works for both English and Chinese queries about Alibaba Cloud data processing with MaxFrame.