fix(#2443): catch fetch() network errors in bindAsyncForms doSubmit

Wrap the fetch() call in a try/catch so network errors (offline, DNS
failure, CORS) surface via themedToast instead of becoming unhandled
promise rejections. The asyncBtn finally() still restores the button
either way — the catch just adds the missing operator feedback.
This commit is contained in:
iris 2026-07-20 19:58:04 +02:00
commit bd7ae83860

View file

@ -85,12 +85,18 @@ export function bindAsyncForms(onSuccess) {
// Errors are surfaced via themedToast; the caller does not re-throw // Errors are surfaced via themedToast; the caller does not re-throw
// so asyncBtn's finally always runs (restoring the button). // so asyncBtn's finally always runs (restoring the button).
const doSubmit = async () => { const doSubmit = async () => {
const resp = await fetch(f.action, { let resp;
method: f.method || 'POST', try {
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, resp = await fetch(f.action, {
body: new URLSearchParams(new FormData(f)), method: f.method || 'POST',
redirect: 'manual', headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
}); body: new URLSearchParams(new FormData(f)),
redirect: 'manual',
});
} catch (err) {
themedToast('action failed: ' + err, { type: 'error' });
return;
}
const ok = resp.ok || resp.type === 'opaqueredirect' const ok = resp.ok || resp.type === 'opaqueredirect'
|| (resp.status >= 200 && resp.status < 400); || (resp.status >= 200 && resp.status < 400);
if (!ok) { if (!ok) {