Collectives™ on Stack Overflow
Find centralized, trusted content and collaborate around the technologies you use most.
Learn more about Collectives
Teams
Q&A for work
Connect and share knowledge within a single location that is structured and easy to search.
Learn more about Teams
I have made a custom error handler for my koa app which works beautifully (except for one sticking point) - using
ctx.throw()
means any stacktrace is emitted to the server logs and also any custom error message is sent in the response.
The
one
problem is that
Content-Type
header is
text/plain
but I really need it to be
application/json
.
app.js
:
import Koa from 'koa';
import bodyParser from 'koa-bodyparser';
import logger from 'koa-morgan';
import authentication from './middleware/authentication';
import config from './config';
import errorHandler from './middleware/error-handler';
import notificationsRoutes from './routes/notifications';
const app = new Koa();
app.use(errorHandler);
app.use(bodyParser());
app.use(logger(config.logLevel));
app.use(authentication);
app.use(notificationsRoutes.routes());
export default app;
error-handler.js
:
export default async (ctx, next) => {
return next().catch(({ statusCode, message }) => {
ctx.throw(statusCode, JSON.stringify({ message }));
(I thought (statusCode, JSON.stringify({ message }));
might coerce the response into application/json
but it doesn't.
I have googled to no avail. Please help!
Managed to modify the error-handler
to produce the desired result. Works really well - stack traces are emitted to server logs and the first line of that message becomes the message
in the response body. The latter might be considered a downside by some but it depends what you're after.
error-handler.js
:
export default async (ctx, next) => {
return next().catch(err => {
const { statusCode, message } = err;
ctx.type = 'json';
ctx.status = statusCode || 500;
ctx.body = {
status: 'error',
message
ctx.app.emit('error', err, ctx);
Found this and used it for reference: https://github.com/koajs/examples/blob/master/errors/app.js
It's worth mentioning that this custom error - ServerError.js
- is used in the app; that's why ctx.status = statusCode || 500
- statusCode
is provided by ServerError
when used, but for non-custom errors that are thrown, statusCode
comes through to error-handler.js
as undefined
so || 500
is needed.
ServerError.js
:
export class ServerError extends Error {
constructor(statusCode, message) {
super(message);
this.statusCode = statusCode;
(usage: throw new ServerError(400, 'my informative error message');
)
Don't have any catch
blocks in any of your middlewares and the error will propagate all the way up to your top errorHandler
middleware in app.js
(which is what you want to happen).
Custom error handling in koa seems to generate many different opinions but this seems to work well for us for now.
–
Add Error handler middleware
server.use(async function jsonErrorHandler(ctx, next) {
try {
await next();
} catch (err: any) {
ctx.status = err.status || err.statusCode || 500;
ctx.body = { message: err };
ctx.app.emit('error', err, ctx);
then throw the error like this:
export async function usersIssuesHandler(context: Context) {
context.throw('some error here',500);
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.