- name
- aidd-error-causes
- description
- Use the error-causes library for structured error handling in JavaScript/TypeScript. Use when throwing errors, catching errors, defining error types, or implementing error routing.
# Error Causes Rule
Use the `error-causes` library for all error handling in JavaScript/TypeScript code to enable structured error handling with named causes.
## Why Error Causes?
- Enables structured error handling with named causes instead of relying on `instanceof` checks
- Works across memory realms (e.g., iframes) unlike `instanceof`
- Provides consistent error metadata (name, code, message, cause)
- Makes error handling explicit and self-documenting
- Allows for automatic error routing based on error names
## Import Statement
```js
import { createError } from "error-causes";
```
## Basic Usage
Instead of throwing plain errors:
```js
// ❌ DON'T
throw new Error('Config key "API_KEY" is required');
```
Use `createError` with structured metadata:
```js
// ✅ DO
throw createError({
name: 'ConfigurationError',
message: 'Required configuration key "API_KEY" is not defined',
code: 'MISSING_CONFIG_KEY',
requestedKey: 'API_KEY'
});
```
## Error Properties
Always include these properties in `createError`:
- `name` - Error name for matching (e.g., 'ValidationError', 'AuthenticationError')
- `message` - Human-readable error message
- `code` (optional) - Error code for programmatic handling
- Custom properties (optional) - Any additional context relevant to the error
## Wrapping Caught Errors
When catching and re-throwing errors, preserve the original error as `cause`:
```js
try {
await someOperation();
} catch (originalError) {
throw createError({
name: 'OperationError',
message: 'Failed to perform operation',
code: 'OPERATION_FAILED',
cause: originalError // Preserve original error
});
}
```
## Factory Validation Errors
For factory functions that validate parameters at creation time:
```js
const createMiddleware = ({ requiredParam } = {}) => {
if (!requiredParam) {
throw createError({
name: 'ValidationError',
message: 'requiredParam is required',
code: 'MISSING_REQUIRED_PARAM'
});
}
return async ({ request, response }) => {
// middleware implementation
};
};
```
## Testing Error Causes
In tests, verify the error's `cause` property:
```js
let error;
try {
functionThatThrows();
} catch (e) {
error = e;
}
assert({
given: 'invalid input',
should: 'throw Error with cause',
actual: error instanceof Error && error.cause !== undefined,
expected: true
});
assert({
given: 'invalid input',
should: 'have correct error name',
actual: error.cause.name,
expected: 'ValidationError'
});
assert({
given: 'invalid input',
should: 'have correct error code',
actual: error.cause.code,
expected: 'MISSING_REQUIRED_PARAM'
});
```
## Error Handler Pattern
For APIs that define multiple error types, use the `errorCauses` pattern:
```js
import { errorCauses, createError } from "error-causes";
// Define all possible errors for your API
const [apiErrors, handleApiErrors] = errorCauses({
NotFound: {
code: 404,
message: 'Resource not found'
},
ValidationError: {
code: 400,
message: 'Invalid input'
},
Unauthorized: {
code: 401,
message: 'Authentication required'
}
});
const { NotFound, ValidationError, Unauthorized } = apiErrors;
// Throw errors
if (!resource) throw createError(NotFound);
// Handle errors with automatic routing
someAsyncCall()
.catch(handleApiErrors({
NotFound: ({ message }) => console.log(message),
ValidationError: ({ message }) => console.log(message),
Unauthorized: ({ message }) => redirect('/login')
}));
```
## Rules
1. **Always use `createError`** instead of `new Error()` for thrown errors
2. **Always include `name` and `message`** in error metadata
3. **Include `code`** when the error needs programmatic handling
4. **Preserve original errors** using the `cause` property when re-throwing
5. **Add context** with custom properties relevant to the error
6. **Test the `cause` property** in error tests, not just the error message
7. **Define error types** using `errorCauses()` for APIs with multiple error types
GitHubで見る