0
# Koa Onerror
1
2
Koa Onerror is an error handling middleware for Koa.js applications that overrides the default `ctx.onerror` method to provide comprehensive error handling. It offers flexible error response formatting with automatic content negotiation, supports both development and production modes, and handles stream errors that can't be caught by traditional try-catch blocks.
3
4
## Package Information
5
6
- **Package Name**: koa-onerror
7
- **Package Type**: npm
8
- **Language**: TypeScript
9
- **Installation**: `npm install koa-onerror`
10
11
## Core Imports
12
13
```typescript
14
import { onerror } from "koa-onerror";
15
// Also available: OnerrorError, OnerrorHandler, OnerrorOptions types
16
```
17
18
For CommonJS:
19
20
```javascript
21
const { onerror } = require("koa-onerror");
22
```
23
24
## Basic Usage
25
26
```typescript
27
import Koa from "koa";
28
import { onerror } from "koa-onerror";
29
30
const app = new Koa();
31
32
// Apply error handling middleware
33
onerror(app);
34
35
// Your other middleware
36
app.use(async (ctx) => {
37
// This error will be handled by koa-onerror
38
throw new Error("Something went wrong!");
39
});
40
41
app.listen(3000);
42
```
43
44
## Architecture
45
46
Koa Onerror works by replacing the default `ctx.onerror` method with a more sophisticated error handler that:
47
48
- **Content Negotiation**: Automatically responds with appropriate format (HTML, JSON, text) based on Accept headers
49
- **Error Normalization**: Converts non-Error objects into proper Error instances
50
- **Stream Cleanup**: Handles and cleans up request streams during error scenarios using `stream-wormhole`
51
- **Development vs Production**: Shows detailed error information in development, sanitized responses in production
52
- **Status Code Management**: Automatically sets appropriate HTTP status codes with fallback to 500
53
- **Header Propagation**: Forwards custom headers from error objects to the response
54
55
## Capabilities
56
57
### Primary Middleware Function
58
59
Main function that configures comprehensive error handling for a Koa application.
60
61
```typescript { .api }
62
/**
63
* Configure error handling middleware for a Koa application
64
* @param app - Koa application instance
65
* @param options - Optional configuration for error handlers
66
* @returns The modified Koa application instance
67
*/
68
function onerror(app: any, options?: OnerrorOptions): any;
69
```
70
71
**Usage Example:**
72
73
```typescript
74
import Koa from "koa";
75
import { onerror } from "koa-onerror";
76
77
const app = new Koa();
78
79
// Basic usage with default handlers
80
onerror(app);
81
82
// With custom options
83
onerror(app, {
84
// Custom JSON error handler
85
json(err, ctx) {
86
ctx.body = {
87
success: false,
88
error: err.message,
89
code: err.status || 500
90
};
91
},
92
93
// Redirect for HTML/text errors
94
redirect: "/error-page",
95
96
// Universal error handler (overrides content negotiation)
97
all(err, ctx) {
98
console.error("Error occurred:", err);
99
ctx.body = "An error occurred";
100
}
101
});
102
```
103
104
### Error Object Types
105
106
Enhanced error object interface used throughout the error handling system.
107
108
```typescript { .api }
109
/**
110
* Extended Error object with additional properties for HTTP error handling
111
*/
112
type OnerrorError = Error & {
113
/** HTTP status code for the error response */
114
status: number;
115
/** Optional HTTP headers to include in the error response */
116
headers?: Record<string, string>;
117
/** Whether to expose detailed error information to clients */
118
expose?: boolean;
119
};
120
```
121
122
### Error Handler Types
123
124
Function signature for custom error handling callbacks.
125
126
```typescript { .api }
127
/**
128
* Custom error handler function signature
129
* @param err - The error object with additional HTTP properties
130
* @param ctx - Koa context object
131
*/
132
type OnerrorHandler = (err: OnerrorError, ctx: any) => void;
133
```
134
135
### Configuration Options
136
137
Comprehensive configuration interface for customizing error handling behavior.
138
139
```typescript { .api }
140
/**
141
* Configuration options for koa-onerror middleware
142
*/
143
type OnerrorOptions = {
144
/** Custom handler for text/plain responses */
145
text?: OnerrorHandler;
146
/** Custom handler for application/json responses */
147
json?: OnerrorHandler;
148
/** Custom handler for text/html responses */
149
html?: OnerrorHandler;
150
/** Universal handler that bypasses content negotiation */
151
all?: OnerrorHandler;
152
/** Custom handler for application/javascript responses (JSONP) */
153
js?: OnerrorHandler;
154
/** Redirect URL for HTML/text errors instead of showing error page */
155
redirect?: string | null;
156
/** Custom content negotiation function */
157
accepts?: (...args: string[]) => string;
158
};
159
```
160
161
**Detailed Option Usage:**
162
163
```typescript
164
onerror(app, {
165
// Override default text handler
166
text(err, ctx) {
167
ctx.body = `Error ${err.status}: ${err.message}`;
168
},
169
170
// Override default JSON handler
171
json(err, ctx) {
172
ctx.body = {
173
error: {
174
message: err.message,
175
status: err.status,
176
timestamp: new Date().toISOString()
177
}
178
};
179
},
180
181
// Override default HTML handler
182
html(err, ctx) {
183
ctx.body = `
184
<h1>Error ${err.status}</h1>
185
<p>${err.message}</p>
186
<p>Please try again later.</p>
187
`;
188
},
189
190
// Handle JSONP responses
191
js(err, ctx) {
192
const callback = ctx.query.callback || 'callback';
193
ctx.body = `${callback}(${JSON.stringify({ error: err.message })})`;
194
},
195
196
// Redirect instead of showing error
197
redirect: '/error-page',
198
199
// Universal handler (overrides content negotiation)
200
all(err, ctx) {
201
// Log error internally
202
console.error('Application Error:', err);
203
204
// Send simple response regardless of Accept header
205
ctx.status = err.status || 500;
206
ctx.body = 'An unexpected error occurred';
207
},
208
209
// Custom content negotiation
210
accepts(...types) {
211
// Custom logic to determine response type
212
return this.get('User-Agent').includes('mobile') ? 'json' : 'html';
213
}
214
});
215
```
216
217
## Error Handling Features
218
219
### Automatic Error Processing
220
221
- **Non-Error Wrapping**: Automatically wraps non-Error objects (strings, objects) in proper Error instances
222
- **Status Code Assignment**: Sets appropriate HTTP status codes (404 for ENOENT, 500 for others)
223
- **Header Management**: Propagates error headers to the response and manages header state
224
- **Stream Cleanup**: Uses `stream-wormhole` to properly dispose of request streams during errors
225
226
### Content Negotiation
227
228
The middleware automatically determines the response format based on the client's `Accept` header:
229
230
- `text/html` → HTML error page (using built-in templates)
231
- `application/json` → JSON error response
232
- `text/plain` → Plain text error message
233
- `application/javascript` → Custom JavaScript/JSONP handling (if `js` handler provided)
234
235
### Development vs Production Modes
236
237
Error exposure is controlled by the `NODE_ENV` environment variable:
238
239
- **Development**: Shows full error messages and stack traces
240
- **Production**: Shows generic HTTP status messages for security
241
242
### Built-in Templates
243
244
The package includes two HTML error templates:
245
246
- **Development Template**: Shows detailed error information with stack traces
247
- **Production Template**: Shows minimal error information for security
248
249
## Error Object Enhancement
250
251
When errors occur, the middleware enhances them with additional properties:
252
253
```typescript
254
// Original error
255
const err = new Error("Database connection failed");
256
257
// Enhanced by koa-onerror
258
err.status = 500;
259
err.headers = { 'X-Error-Code': 'DB_CONN_FAIL' };
260
err.expose = false; // Don't expose in production
261
262
// The enhanced error is then processed by the appropriate handler
263
```
264
265
## Integration with Koa
266
267
The middleware integrates seamlessly with Koa's error handling system:
268
269
1. **Event Emission**: All errors are emitted on the app instance for logging
270
2. **Context Integration**: Replaces `ctx.onerror` method on all contexts
271
3. **Response Management**: Handles response completion and header management
272
4. **Stream Management**: Automatically handles request stream cleanup
273
274
## Common Use Cases
275
276
### API Error Responses
277
278
```typescript
279
onerror(app, {
280
json(err, ctx) {
281
ctx.body = {
282
success: false,
283
error: {
284
code: err.code || 'UNKNOWN_ERROR',
285
message: err.message,
286
status: err.status || 500
287
},
288
requestId: ctx.state.requestId
289
};
290
}
291
});
292
```
293
294
### Custom Error Pages
295
296
```typescript
297
onerror(app, {
298
html(err, ctx) {
299
const errorPage = getErrorTemplate(err.status);
300
ctx.body = errorPage.replace('{{message}}', err.message);
301
},
302
redirect: null // Don't redirect, use custom template
303
});
304
```
305
306
### Logging Integration
307
308
```typescript
309
onerror(app, {
310
all(err, ctx) {
311
// Log error with context
312
logger.error('Request error', {
313
error: err.message,
314
stack: err.stack,
315
url: ctx.url,
316
method: ctx.method,
317
userAgent: ctx.get('User-Agent'),
318
ip: ctx.ip
319
});
320
321
// Then handle normally based on content type
322
const type = ctx.accepts('html', 'json', 'text');
323
if (type === 'json') {
324
ctx.body = { error: 'Internal server error' };
325
} else {
326
ctx.body = 'An error occurred';
327
}
328
}
329
});
330
```