-
-
Notifications
You must be signed in to change notification settings - Fork 124
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Debugging errors in the backend #86
Comments
Why prefer this over django's default debug page? |
@adamchainz the default behavior is that the Javascript console will display an ambiguous error with little information related to the request from the backend. |
Ah right, because the response code is 500 htmx doesn't insert it. There might be some way we can adjust django's debug view or htmx to work rather than reimplement it ourselves - that would be preferable? |
I think it will not be possible to repurpose Django's debug view in the case of partial rendering multiple elements in a page. Perhaps we can do this in HTMX itself, but I think there is a known limitation related to how much we might expect here. The solution I found seemed to me the most obvious choice, but I could pursue a different solution if you think there is a better way of doing this. |
My current solution could be changed to use Django debug methods similar to technical_500_response. The main advantage of doing it this way is that if multiple error responses are encountered then each element will produce a debug output. import sys
from django.conf import settings
from django.http import HttpResponse
from django.views.debug import get_exception_reporter_class
from django_htmx.middleware import HtmxMiddleware
class HtmxDebugMiddleware(HtmxMiddleware):
def process_exception(self, request, exception):
if request.htmx and settings.DEBUG:
reporter = get_exception_reporter_class(request)(request, *sys.exc_info())
content = reporter.get_traceback_text()
return HttpResponse(content, content_type="text/plain; charset=utf-8")
return None However, there are some limitations/potential issues:
An alternative could be to persist the error context in the session and redirect on the first error encountered, though I haven't tried doing it this way myself at this point. I'm thinking something (roughly) like this could work:
If either of these solutions seem like a good fit for this library, then I would be happy to explore/test further and put forward a PR. |
I’ve had a play around and I think we can handle this entirely in JavaScript, with no server side changes. The problem is really that htmx throws away Django’s useful error response, working around this on the server side is just going to be harder than intersecting the behaviour on the front end. Here’s an example script I managed to get working: document.addEventListener("htmx:beforeOnLoad", function (event) {
const xhr = event.detail.xhr;
if (xhr.status == 500) {
document.children[0].innerHTML = xhr.response;
const url = new URL(xhr.responseURL);
history.pushState({}, "", url.pathname + url.search);
}
}); This puts Django’s error response full screen on the page. It doesn’t currently handle reloading the scripts, but I think we can work around this by having htmx process the response - I'm currently researching. |
I've tried your script and have been able to make the Django error response work as you described, and I have a couple questions/a comment:
|
I would make it only appear on pages when DEBUG = True, with a template tag.
Please please please never run with For errors in other environments, use a tool like Sentry.
Yes, I'd probably ship it via a template tag that inserts a
If there is more than one error from requests made on the page, either the requests are queued at the same time, or not. If they are not queued at the same time, the first one will hit the error case, the full page will be replaced, and then htmx should see all the other elements as removed and not fire their events. If they are queued at the same time, both their responses will be parsed, and both error messages displayed. So they will at least be held in history. I'm not so bothered about the possibility for multiple errors. Once you've fixed the first, you can debug and fix the second. |
Yes, my concern was for the case when debug is not enabled and the script replaces the page with non-debug server error response. The templatetag approach should resolve this by only running this behaviour when debug is enabled.
The potential confusion I was alluding to was that in the process of debugging some cases (e.g multiple load triggers) it might seem like the first error was resolved by some change after reloading the page and a different error just happens to return before the previous error is encountered again. That said, all of this information is still captured both in the backend and console, so it is still visible somewhere - just not immediately obvious. Thank you for investigating this. |
Ah good, my misunderstanding... I've just seen too many people running debug mode in prod 😅
Yes this is true. I'm not sure there's much we can do about that. Thankfully most pages should be fairly deterministic in the order that errors occur. |
Just released in version 1.2.0 - check it out! |
Hello, firstly I want to say thank you because I find this project very useful! I was finding it difficult to debug some errors in a project that I'm working on, so I subclassed the middleware to return errors to the frontend like this:
Here is an example of what the solution above produces when
raise RuntimeError("Something bad happened on the backend!")
is encountered:Would it be desirable to include something similar in this project?
The text was updated successfully, but these errors were encountered: