Handling 4xx/5xx HTTP Statuses with HX-Retarget and HX-Reswap
- Last updated
- Prerequisites:
- HTTP Status Codes (200, 422, 500)
- HTMX response headers
- htmx
- status-codes
- hx-retarget
- hx-reswap
- error-handling
- headers
Read at your depth
The practical view
By default, HTMX **only swaps content on 2xx successful HTTP status codes**. If the server returns a 4xx (e.g. `400 Bad Request`, `422 Unprocessable Entity`) or 5xx error, HTMX triggers `htmx:responseError` and skips swapping. The server can override this behavior by returning the `HX-Retarget: #error-div` and `HX-Reswap: innerHTML` headers alongside the error status code to render validation errors.
The same idea in other frameworks
`catch (err) { setError(err.response.data.message); }` inside form submit.HTTP Interceptor catching `HttpErrorResponse` and mapping to form errors.Axios / `$fetch` `onError` handler setting component error ref.Server returns HTTP 422 with `HX-Retarget: #errors` and HTML error partial.Legacy vs modern
Anti-Pattern HTTP 200 Fake Errors vs Semantic HTTP 422 + HX-Retarget
Returning HTTP 200 for errors violates HTTP standards; HTTP 422 with `HX-Retarget` preserves semantics and redirects errors cleanly.
res.status(200).send('<div class="error">Invalid</div>'); // ❌ Confuses monitoring & cachingres.set('HX-Retarget', '#error-box').status(422).send('<p>Invalid</p>'); // ✅ NEWInterview gotchas
Context
Interviewers test your knowledge of HTMX global configuration and the `response-targets` extension.
The mechanical answer
You can use the official **`response-targets` extension** (`hx-ext="response-targets"`) and declarative attributes like `hx-target-422="#validation-errors"` or `hx-target-500="#server-error"`. Alternatively, intercept `htmx:beforeOnLoad` in JS: `document.body.addEventListener('htmx:beforeOnLoad', (evt) => { if (evt.detail.xhr.status === 422) evt.detail.shouldSwap = true; });`.
Trap
Without either `response-targets`, `HX-Retarget` headers, or `htmx:beforeOnLoad`, HTMX will completely ignore 4xx/5xx response bodies.
Context
Checks precision regarding target location vs source fragment extraction.
The mechanical answer
`HX-Retarget: #some-id` changes the **destination element in the active DOM** where the response will be swapped. `HX-Reselect: #some-id` changes which **portion of the incoming HTML response** will be extracted and swapped into the target (equivalent to `hx-select`).
Trap
Do not confuse source selection (`HX-Reselect`) with destination target redirection (`HX-Retarget`).