html_url,issue_url,id,node_id,user,created_at,updated_at,author_association,body,reactions,issue,performed_via_github_app https://github.com/simonw/datasette/issues/1770#issuecomment-1185925081,https://api.github.com/repos/simonw/datasette/issues/1770,1185925081,IC_kwDOBm6k_c5Gr8fZ,9599,2022-07-15T20:55:41Z,2022-07-15T20:56:16Z,OWNER,"I think the hook gets called any time any exception makes it to this function: https://github.com/simonw/datasette/blob/950cc7677f65aa2543067b3bbfc2b6acb98b62c8/datasette/app.py#L1374-L1440 Multiple plugins can register for the hook. If they return a `Response` then that's returned to the user - if they return `None` then they can quietly do something with the error (log it to Sentry for example) and let some other handler return a response. I think Datasette should have a default plugin hook implementation which returns the 500 error page.","{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",1306492437, https://github.com/simonw/datasette/issues/1770#issuecomment-1185929360,https://api.github.com/repos/simonw/datasette/issues/1770,1185929360,IC_kwDOBm6k_c5Gr9iQ,9599,2022-07-15T20:58:11Z,2022-07-15T20:58:11Z,OWNER,"Proposed hook design: ```python @hookspec def handle_exception(datasette, request, exception): """"""Handle an uncaught exception"""""" ``` It takes `request` in case it needs to render a template and pass the request to it.","{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",1306492437, https://github.com/simonw/datasette/issues/1770#issuecomment-1185931417,https://api.github.com/repos/simonw/datasette/issues/1770,1185931417,IC_kwDOBm6k_c5Gr-CZ,9599,2022-07-15T20:59:25Z,2022-07-15T20:59:25Z,OWNER,"... maybe it should take `send`? But then how would plugins know that another plugin hadn't already used `send` to send a response, and avoid two trying to send at the same time?","{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",1306492437, https://github.com/simonw/datasette/issues/1770#issuecomment-1185933972,https://api.github.com/repos/simonw/datasette/issues/1770,1185933972,IC_kwDOBm6k_c5Gr-qU,9599,2022-07-15T21:00:56Z,2022-07-15T21:00:56Z,OWNER,It's weird to return a `Response` though because the code in question lives in `DatasetteRouter` which currently works outside of the layer where responses happen - everything in that class at the moment works using `send` directly.,"{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",1306492437, https://github.com/simonw/datasette/issues/1770#issuecomment-1185935764,https://api.github.com/repos/simonw/datasette/issues/1770,1185935764,IC_kwDOBm6k_c5Gr_GU,9599,2022-07-15T21:02:00Z,2022-07-15T21:02:12Z,OWNER,Returning a `Response` is by far the most intuitive way to design this though. Plugin authors shouldn't care that `DatasetteRouter` (an undocumented internal API of Datasette) doesn't currently handle responses.,"{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",1306492437, https://github.com/simonw/datasette/issues/1770#issuecomment-1185937664,https://api.github.com/repos/simonw/datasette/issues/1770,1185937664,IC_kwDOBm6k_c5Gr_kA,9599,2022-07-15T21:03:09Z,2022-07-17T22:25:44Z,OWNER,"Design decision: ```python @hookspec def handle_exception(datasette, request, exception): """"""Handle an uncaught exception. Can return a Response or None."""""" ``` It will also support returning an awaitable, using the `await_me_maybe` pattern.","{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",1306492437, https://github.com/simonw/datasette/issues/1770#issuecomment-1185939664,https://api.github.com/repos/simonw/datasette/issues/1770,1185939664,IC_kwDOBm6k_c5GsADQ,9599,2022-07-15T21:04:19Z,2022-07-15T21:04:19Z,OWNER,I'll implement this hook and then release it as `0.62a1`.,"{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",1306492437, https://github.com/simonw/datasette/issues/1770#issuecomment-1185943887,https://api.github.com/repos/simonw/datasette/issues/1770,1185943887,IC_kwDOBm6k_c5GsBFP,9599,2022-07-15T21:07:53Z,2022-07-15T21:07:53Z,OWNER,In `DatasetteRouter` I'm going to rename `handle_500` to `handle_exception` because it already deals with error codes other than 500 (`Forbidden` exceptions become 403 and `Base400` become 400).,"{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",1306492437, https://github.com/simonw/datasette/issues/1770#issuecomment-1185944799,https://api.github.com/repos/simonw/datasette/issues/1770,1185944799,IC_kwDOBm6k_c5GsBTf,9599,2022-07-15T21:09:08Z,2022-07-15T21:09:08Z,OWNER,Had to lookup that `Base400` thing: https://github.com/simonw/datasette/blob/950cc7677f65aa2543067b3bbfc2b6acb98b62c8/datasette/utils/asgi.py#L16-L29,"{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",1306492437, https://github.com/simonw/datasette/issues/1770#issuecomment-1186620168,https://api.github.com/repos/simonw/datasette/issues/1770,1186620168,IC_kwDOBm6k_c5GumMI,9599,2022-07-17T22:37:01Z,2022-07-17T22:37:01Z,OWNER,"I need to refactor this code so that `Forbidden` exceptions are handled separately. Reason is that those already have a plugin hook of their own: https://github.com/simonw/datasette/blob/8188f55efc0fcca1be692b0d0c875f2d1ee99f17/datasette/app.py#L1384-L1395 My first attempt at this refactored that entire `handle_exception` method to call the new plugin hook, moving its current implementation into a `datasette/handle_exception.py` default plugin implementation - but it felt weird having that plugin implementation then itself call the `pm.hook.forbidden()` hook.","{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",1306492437, https://github.com/simonw/datasette/issues/1770#issuecomment-1186620367,https://api.github.com/repos/simonw/datasette/issues/1770,1186620367,IC_kwDOBm6k_c5GumPP,9599,2022-07-17T22:38:25Z,2022-07-17T22:38:25Z,OWNER,I think this is the right place to move the code to catch `Forbidden` exceptions (and forwards them to that plugin hook): https://github.com/simonw/datasette/blob/8188f55efc0fcca1be692b0d0c875f2d1ee99f17/datasette/app.py#L1269-L1278,"{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",1306492437, https://github.com/simonw/datasette/issues/1770#issuecomment-1186629556,https://api.github.com/repos/simonw/datasette/issues/1770,1186629556,IC_kwDOBm6k_c5Guoe0,9599,2022-07-17T23:25:08Z,2022-07-17T23:25:08Z,OWNER,Keeping this issue open until I've proven the new plugin hook works by releasing a plugin that uses it.,"{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",1306492437, https://github.com/simonw/datasette/issues/1770#issuecomment-1186630298,https://api.github.com/repos/simonw/datasette/issues/1770,1186630298,IC_kwDOBm6k_c5Guoqa,9599,2022-07-17T23:29:37Z,2022-07-17T23:29:37Z,OWNER,Documentation for the new hook: https://docs.datasette.io/en/latest/plugin_hooks.html#handle-exception-datasette-request-exception,"{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",1306492437, https://github.com/simonw/datasette/issues/1770#issuecomment-1214400698,https://api.github.com/repos/simonw/datasette/issues/1770,1214400698,IC_kwDOBm6k_c5IYki6,9599,2022-08-14T15:25:51Z,2022-08-14T15:25:51Z,OWNER,I've tested this with `datasette-sentry` and it works well.,"{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",1306492437,