Requests and responses
Use status codes deliberately
Distinguish success, validation failure, missing resources, and server failure so HTMX and your error handling can react correctly.
HTTP status and swap behavior are related but separate decisions. The status code tells HTMX whether the response body is a normal success payload or an error. Your swap settings decide what happens next.
Successful 2xx responses normally swap their HTML. 204 No Content is a deliberate exception: HTMX performs no content swap. It fits an operation whose visible result arrives through an out-of-band update or event. Do not use it when the user needs confirmation text in the target.
Error responses such as 404, 422, and 500 are not swapped by default. HTMX triggers htmx:responseError, and htmx:beforeSwap receives shouldSwap: false. The old DOM stays in place, which is usually what you want for a server crash or a missing record.
Keep accurate status codes. Do not return 200 for every failure merely to force markup into the page. That hides real errors from your monitoring and from HTMX’s event hooks. Instead, explicitly allow a safe validation fragment when you mean to show field errors:
document.addEventListener('htmx:beforeSwap', event => {
if (event.detail.xhr.status === 422) {
event.detail.shouldSwap = true
event.detail.isError = false
}
})
Use this only when the 422 body is designed for the target. A generic proxy error page or stack trace must not be swapped into a form. I keep a dedicated validation partial for forms and return it with 422 so the listener has something safe to insert.
Force each status in development and inspect the event, response body, target, and final DOM. Return 422 with your form errors and confirm the swap happens. Return 500 with an HTML error page and confirm the form stays untouched.
Try this on your own project: submit invalid data and verify the server returns 422, not 200 with an error string buried in a success template.
Lesson completed