History, errors, and enhancement
Handle connection errors
Distinguish a server response from a request that never completed and provide a retry path.
8 minute lesson
A connection error is different from an HTTP error: no usable server response arrived. HTMX emits htmx:sendError. Timeouts and aborted requests emit their own events.
Provide one shared recovery path:
document.addEventListener("htmx:sendError", () => {
const status = document.querySelector("#connection-status")
if (status) status.textContent = "Connection lost. Check your network and retry."
})
HTMX removes request-state classes and restores elements managed by hx-disabled-elt as the lifecycle ends. Preserve safe form input, replace indefinite “Saving…” text, and leave a clear retry control.
For a state-changing request, “no response” does not prove “nothing happened.” The server may have committed the operation before the connection failed. Blindly retrying a purchase or create request can duplicate it.
Use idempotency keys for costly operations, or reconcile by fetching the current server state before retrying. Phrase the message honestly: “We could not confirm the result” is more accurate than “Save failed.”
Test offline mode, timeout, abort, and a real 500 separately. They should not all collapse into the same diagnosis.
Lesson completed