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