# Exception

> Exception Handling

- Skill: `harshamendu/exception` (Agent Skill, multi-file: 7 files)
- Install (CLI): `npx skillmds@latest add harshamendu/exception`
- Raw SKILL.md: https://api.skillmd.com/api/skills/harshamendu/exception/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: Harshamendu (https://skillmd.com/u/harshamendu)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/harshamendu/exception

---

# Exception Handling

> **📝 Note:** This guide uses generic placeholder names to be reusable across any Spring Boot microservice.
> Replace with your actual implementation:
> - `{YourService}` → Your service name (e.g., `OrderService`, `PaymentService`)
> - `BusinessService` → Your core service (e.g., `OrderService`, `UserService`)
> - `DataService` → Your data processing service (e.g., `PaymentService`, `InventoryService`)
> - `IntegrationService` → Your external integration (e.g., `PaymentGatewayService`)
> - `{RequestType}` → Your request DTO (e.g., `CreateOrderRequest`)
> - `{ResponseType}` → Your response DTO (e.g., `OrderResponse`)


## Quick Reference

### Package Location
```
exception/
├── RequestUnauthorizedExceptionWithSubcode.java  # 401 with subcode
└── handler/
    ├── AlreadyExistsWithSubcodeException.java    # 409 with subcode
    └── AppExceptionHandler.java                  # Global exception handler
```

### Example Package
```java
com.example.microserviceorch.exception.example
```

## Key Patterns

### 1. Custom Exception with Subcode
```java
throw new RequestUnauthorizedExceptionWithSubcode(
    "Account does not have a password", 
    "no_password"
);
```

### 2. Fluent Builder Pattern
```java
throw new AlreadyExistsWithSubcodeException("Account already exists")
    .withSubcode("no_password");
```

### 3. Global Exception Handler
```java
@ControllerAdvice
@ResponseBody
public class AppExceptionHandler extends ApiExceptionHandler {
    @ExceptionHandler({RequestUnauthorizedException.class})
    public ResponseEntity<GeneralError> requestUnauthorizedException(
            RequestUnauthorizedException e) {
        LOG.warn("{}{}, 401", e.getClass().getCanonicalName(), e.getMessage());
        return this.createGeneralError("Unauthorized request", HttpStatus.UNAUTHORIZED);
    }
}
```

### 4. Exception Translation
```java
try {
    accountApiClient.postPasswordlessAccount(email);
} catch (HttpProxyCallException e) {
    if (e.getHttpStatusCode() == 409) {
        throw translateConflictException(e);
    }
}
```

## HTTP Status Mapping

| Exception | Status | Response |
|-----------|--------|----------|
| `BadRequestException` | 400 | `GeneralError` |
| `RequestUnauthorizedException` | 401 | `GeneralError` |
| `RequestUnauthorizedExceptionWithSubcode` | 401 | `SchemasErrorWithSubcode` |
| `AlreadyExistsWithSubcodeException` | 409 | `SchemasErrorWithSubcode` |
| `InternalServerException` | 500 | `GeneralError` |

## Error Response Schemas

### GeneralError
```json
{
  "success": false,
  "status": 400,
  "error": "Invalid input parameter"
}
```

### SchemasErrorWithSubcode
```json
{
  "success": false,
  "status": 401,
  "error": "Account does not have a password set",
  "subcode": "no_password"
}
```

## Detailed Documentation

- **Architecture**: [guides/architecture.md](guides/architecture.md)
- **Best Practices**: [guides/best-practices.md](guides/best-practices.md)
- **Testing**: [guides/testing.md](guides/testing.md)
- **Examples**: [examples/README.md](examples/README.md)

## Code Formatting
```bash
./gradlew spotlessApply
```

