diff --git a/lib/context.js b/lib/context.js index e7b10b8..a537cb9 100644 --- a/lib/context.js +++ b/lib/context.js @@ -5,6 +5,7 @@ * Module dependencies. */ +const util = require('util'); const createError = require('http-errors'); const httpAssert = require('http-assert'); const delegate = require('delegates'); @@ -105,7 +106,7 @@ const proto = module.exports = { // to node-style callbacks. if (null == err) return; - if (!(err instanceof Error)) err = new Error(`non-error thrown: ${err}`); + if (!(err instanceof Error)) err = new Error(util.format('non-error thrown: %j', err)); let headerSent = false; if (this.headerSent || !this.writable) { diff --git a/test/context/onerror.js b/test/context/onerror.js index 87f7556..ddee81c 100644 --- a/test/context/onerror.js +++ b/test/context/onerror.js @@ -185,5 +185,23 @@ describe('ctx.onerror(err)', () => { assert.equal(removed, 2); }); + + it('should stringify error if it is an object', done => { + const app = new Koa(); + + app.on('error', err => { + assert.equal(err, 'Error: non-error thrown: {"key":"value"}'); + done(); + }); + + app.use(async ctx => { + throw {key: 'value'}; // eslint-disable-line no-throw-literal + }); + + request(app.callback()) + .get('/') + .expect(500) + .expect('Internal Server Error', () => {}); + }); }); });