or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

tessl/npm-koa-onerror

Comprehensive error handling middleware for Koa.js applications that overrides ctx.onerror with flexible response formatting

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/koa-onerror@5.0.x

To install, run

npx @tessl/cli install tessl/npm-koa-onerror@5.0.0

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

```