Findings No. 75
SvelteKit's `use:enhance` ignores `preventDefault()` from your own `onsubmit` handler, so a `confirm()` there cannot stop the submission
SvelteKit's use:enhance calls preventDefault() itself and never checks defaultPrevented, so a confirm() in onsubmit cannot cancel. Use cancel() instead.
In a client portal, an admin clicked a button to remove a team member, a confirm dialog asked whether to go ahead, and the admin clicked Cancel. The member was removed anyway. The form used use:enhance, and the confirm ran in an onsubmit handler that called event.preventDefault() when the answer was no.
The cause is in SvelteKit's own submit listener. In @sveltejs/kit 3.1.0, src/runtime/app/forms/client.js attaches handle_submit to every enhanced form. For a POST form it calls event.preventDefault() itself, builds the FormData and sends the request with fetch. It never reads event.defaultPrevented, so a handler that already prevented the default changes nothing. The only check that can stop the request is a cancelled flag, set by the cancel function that Kit passes to your enhance callback.
The same bug shipped three times in that project before it was caught: removing a team member, revoking an invitation, and enabling a per-organization opt-in setting.
The fix is to ask inside the enhance callback:
<form method="POST" use:enhance={({ cancel }) => {
if (!confirm("Remove this member?")) cancel();
}}>
The project now has a small confirmFirst(question) helper that wraps this pattern, so it is written once and reused. Plain forms without use:enhance can keep onsubmit with preventDefault(), because there the browser's own submission is the only one.
Rule: on an enhanced form, cancel() in the enhance callback is the only way to stop the request. Any confirm on such a form deserves a test that clicks Cancel.
Receipt: Client Portal, @sveltejs/kit 3.1.0 src/runtime/app/forms/client.js (handle_submit); client project changelog 0.38.0.