Error: next() called multiple times
kpopovic opened this issue · comments
Hello,
when defined multiple http status codes in output
error is thrown.
- when only "400-599" is defined then ot works
- when "400-599" and 200 are defined the error is thrown.
It seams that it has issues wtih multiple status codes.
const joiSchema = {
body: {
email: Joi.string()
.lowercase()
.email()
.max(45)
.required(),
password: Joi.string()
.max(10)
.required()
},
output: {
200: {
body: {
jwtToken: Joi.string()
.alphanum()
.min(3)
.max(200)
.required()
}
},
"400-599": {
body: {
error: Joi.object()
}
}
},
type: "json",
continueOnError: true
};
Error: next() called multiple times
at dispatch (/home/kresimir/Development/zimmerfrei/zimmerfrei-http-server/node_modules/koa-router/node_modules/koa-compose/index.js:38:45)
at next (/home/kresimir/Development/zimmerfrei/zimmerfrei-http-server/node_modules/koa-router/node_modules/koa-compose/index.js:45:18)
at errorHandler (/home/kresimir/Development/zimmerfrei/zimmerfrei-http-server/node_modules/koa-joi-router/joi-router.js:285:22)
at process._tickCallback (internal/process/next_tick.js:68:7)
Thank you for the report. I'm unable to reproduce this one. When you get a chance, could you provide a script I ran run which reproduces the error?
@aheckmann
Did you capture validation error and handler-generated error with same handler which will check continueOnError
and call next()
?
@aheckmann
Seems only happen on validated body? I'm not sure.
const Koa = require('koa')
const Router = require("koa-joi-router")
const Joi = Router.Joi
const app = new Koa()
const router = new Router()
router.get("/", async (ctx, next) => {
ctx.body = `
<form action="/test" method="post">
<input type="text" name="q" value="test" />
<input type="submit" value="submit" />
</form>`
})
router.post("/test", {
validate: {
type: "form",
body: { q: Joi.string().required(), },
continueOnError: true
},
}, async (ctx, next) => {
throw new Error("test error")
})
app.use(router.middleware())
app.listen(80, () => console.log("App running."))
Hello,
I gave up on "koa-joi-router", don't use it any more. Deleted the project sample with this error.
Sorry.
I my case same error is appearing when continueOnError: true
but the error is not informed by Joi for example an undefined var on handler body
handler : async () => {
// const a = 1
await otherTier.myFunction(a)
}
So, I've simple add the validation (for testing) if the error is a joi error in order to continue whenever joi use continueOnError === true, otherwise the error must be thrown
if (!(err.isJoi && spec.validate.continueOnError)) return ctx.throw(err);
if (err.isJoi && spec.validate.continueOnError) {
return await next();
} else {
return ctx.throw(err);
}
Confirming. Sadly, the issue still exists in the latest version. Steps to reproduce:
validate: {
...
continueOnError: true
},
handler: async (ctx) => {
if (ctx.invalid) {
const e = ctx.invalid.body.details[0];
ctx.throw(406, JSON.stringify({ errors: { [e.context.key]: e.message } }));
}
}
Call that endpoint and you'll get:
Error: next() called multiple times
at dispatch (PROJECT_PATH\node_modules\koa-compose\index.js:38:45)
at next (PROJECT_PATH\node_modules\koa-compose\index.js:45:18)
at errorHandler (PROJECT_PATH\node_modules\koa-joi-router\joi-router.js:285:22)
The problem is that when you throw an error (either in code explicitly or by runtime) in the route handler, the errorHandler
catch the error and calls next() which breaks koa's compose function.
Although "an undefined var on handler body" is not a good example, @rolivares 's workaround works for custom errors, which is my case, but won't work if I throw the Joi error from ctx.invalid as-is, which maybe nobody would really do that, it still should be taken into consideration IMO.