# Handling errors We've already briefly touched handling errors in dispatchers in the Getting Started section, but let's dive a bit deeper. ## Registering a handler An error handler for a Dispatcher is simply a function that is called whenever an error is thrown inside one of the handlers. For convenience, that function has access to the error itself, the parsed update and the [state](./state) (if applicable): ```ts dp.onNewMessage( filters.command('do_stuff'), async (msg) => { throw new Error('Some error') } ) dp.onError(async (error, update, state) => { if (update.name === 'new_message') { await update.data.replyText(`Error: ${error.message}`) return true } return false }) ``` Error handler function is expected to return `boolean` indicating whether the update was handled. If it was not, it will be propagated to Client. `update` is an object that contains 2 fields: `name` and `data`. `name` is simply update name (`new_message`, `edit_message`, etc.; see [Handlers](handlers.html)), and `data` is the respective object. ## What errors are not handled Errors inside [Raw update handlers](handlers.html#raw-updates) are not handled by the error handler. Any other errors within the same dispatcher (both handlers and filters) are handled by it. ## Propagation ### To Client If the error handler is not registered, throws an error or returns `false`, the error is propagated to Client's [error handler](../intro/errors.html#client-errors). Obviously, in Client's error handler you won't have access to the update that caused this error: ```ts dp.onNewMessage( filters.command('do_stuff'), async (msg) => { throw new Error('Some error') } ) tg.onError((err) => { // will be called since there's no `dp.onError` console.log(err) }) ``` ### Within the Dispatcher When an error is thrown by one of the handlers, propagation within this dispatcher stops (the same way as if it returned `StopPropagation`): ```ts dp.onNewMessage( filters.command('do_stuff'), async (msg) => { throw new Error('Some error') } ) dp.onNewMessage( async (msg) => { // will not reach } ) ``` ### To parent/children Errors are **not** propagated to parent dispatcher or to any of the children dispatchers: ```ts const dp = new Dispatcher(tg) const dp1 = new Dispatcher() const dp2 = new Dispatcher() dp.addChild(dp1) dp1.addChild(dp2) // dp --child--> dp1 --child--> dp2 dp.onError(() => console.log('DP caught error')) dp1.onError(() => console.log('DP1 caught error')) dp2.onError(() => console.log('DP2 caught error')) dp1.onNewMessage(() => { throw new Error() }) // Only "DP1 caught error" will ever be printed ``` However, if you need that behaviour, you can use `propagateErrorToParent`: ```ts const dp = new Dispatcher(tg) const dp1 = new Dispatcher() const dp2 = new Dispatcher() dp.addChild(dp1) dp1.addChild(dp2) // dp --child--> dp1 --child--> dp2 dp.onError(() => console.log('DP caught error')) dp1.onError(() => { console.log('DP1 caught error') return dp1.propagateErrorToParent(...arguments) }) dp2.onError(() => console.log('DP2 caught error')) dp1.onNewMessage(() => { throw new Error() }) // "DP1 caught error" and "DP caught error" will be printed for each new message ```