Yoctol / bottender

⚡️ A framework for building conversational user interfaces.
https://bottender.js.org
MIT License
4.19k stars 332 forks source link

Error handler failed to reply text #951

Open momocow opened 2 years ago

momocow commented 2 years ago

Describe the bug A clear and concise description of what the bug is.

Using Line platform, replying text in the error handler (aka _error.js) did not actually send replied text to Line following the guide for error handling in Line.

To Reproduce Steps to reproduce the behavior:

  1. Make the entry action throw an Error. (index.js)

    module.exports = async function App (ctx) {
    throw new Error('test');
    }
  2. Set up error handler in _error.js.

    module.exports = async function handleError(ctx, props) {
    await ctx.replyText('something wrong 😰');
    console.error(props.error);
    console.log(ctx);
    };
  3. Trigger the action by saying anything to the bot.

  4. Nothing is replied from the bot, but in the console we can see the error and the context printed.

I found that on the context object, ctx._shouldBatch is still true which will cause all calls to ctx.replyText() buffered.

_isReplied: false,
_replyMessages: [ { type: 'text', text: 'something wrong 😰' } ],
_pushMessages: [],
_shouldBatch: true,
_sendMethod: 'reply'

Expected behavior A clear and concise description of what you expected to happen.

The bot should reply "something wrong 😰".

Additional context Add any other context about the problem here.

Since the ctx.handlerDidEnd() was skipped (as the following snippet) while the error happened and also ctx._shouldBatch was still true, the reply was left in the buffer without sending it out.

https://github.com/Yoctol/bottender/blob/7c400c77d829552d99073b6fb29b2318d2927248/packages/bottender/src/bot/Bot.ts#L287-L298

momocow commented 2 years ago

By calling manually await ctx.handlerDidEnd() the problem can be fixed. (The bot manages to reply the error.)

module.exports = async function handleError(ctx, props) {
  await ctx.replyText('something wrong 😰');
  console.error(props.error);
  console.log(ctx);
  await ctx.handlerDidEnd?.();
};