fix: clear issues upon passing validation (#14683)
authorSimon H <5968653+dummdidumm@users.noreply.github.com>
Thu, 20 Nov 2025 13:17:56 +0000 (14:17 +0100)
committerGitHub <noreply@github.com>
Thu, 20 Nov 2025 13:17:56 +0000 (14:17 +0100)
Fixes #14646

.changeset/busy-planes-cover.md [new file with mode: 0644]
packages/kit/src/runtime/client/remote-functions/form.svelte.js
packages/kit/test/apps/basics/src/routes/remote/form/validate/+page.svelte
packages/kit/test/apps/basics/src/routes/remote/form/validate/form.remote.ts
packages/kit/test/apps/basics/test/test.js

diff --git a/.changeset/busy-planes-cover.md b/.changeset/busy-planes-cover.md
new file mode 100644 (file)
index 0000000..73ee57c
--- /dev/null
@@ -0,0 +1,5 @@
+---
+'@sveltejs/kit': patch
+---
+
+fix: clear issues upon passing validation
index 02bbf92397208efa92cdf988e143956a7c629530..c9696fa97f0d7e43fcb1767ef277f466aa9213fe 100644 (file)
@@ -203,6 +203,9 @@ export function form(id) {
 
                                        const form_result = /** @type { RemoteFunctionResponse} */ (await response.json());
 
+                                       // reset issues in case it's a redirect or error (but issues passed in that case)
+                                       raw_issues = [];
+
                                        if (form_result.type === 'result') {
                                                ({ issues: raw_issues = [], result } = devalue.parse(form_result.result, app.decoders));
 
index 6d53630be4acdd2ceb6ba368f593961d1b8207c1..2ccb5e5ba745ee8a17405d612d082eda702c3006 100644 (file)
@@ -1,5 +1,5 @@
 <script>
-       import { issue_path_form, my_form } from './form.remote.js';
+       import { issue_path_form, my_form, my_form_2 } from './form.remote.js';
        import * as v from 'valibot';
 
        const schema = v.object({
@@ -8,7 +8,7 @@
                button: v.optional(v.literal('submitter'))
        });
        let submitter;
-       $inspect(my_form.fields.allIssues());
+       let error = $state(false);
 </script>
 
 <form id="my-form" {...my_form.preflight(schema)} oninput={() => my_form.validate()}>
@@ -33,6 +33,7 @@
                <p>{issue.message}</p>
        {/each}
 </form>
+
 <button
        id="trigger-validate"
        onclick={() => my_form.validate({ includeUntouched: true, submitter })}
        </button>
        <pre id="allIssues">{JSON.stringify(issue_path_form.fields.allIssues())}</pre>
 </form>
+
+<form
+       id="my-form-2"
+       {...my_form_2.enhance(async ({ submit }) => {
+               error = false;
+               try {
+                       await submit();
+               } catch {
+                       error = true;
+               }
+       })}
+>
+       {#each my_form_2.fields.baz.issues() as issue}
+               <p>{issue.message}</p>
+       {/each}
+
+       <input {...my_form_2.fields.baz.as('text')} />
+
+       <p data-error>{error ? 'An error occurred' : 'No error'}</p>
+
+       <button>submit</button>
+</form>
index c3ae78ab9854af66167a832036bb97f7cb74af06..3e5b2826baa8272b82dd8c92843926459f5585f8 100644 (file)
@@ -1,4 +1,5 @@
 import { form } from '$app/server';
+import { error } from '@sveltejs/kit';
 import * as v from 'valibot';
 
 export const my_form = form(
@@ -17,6 +18,15 @@ export const my_form = form(
        }
 );
 
+export const my_form_2 = form(
+       v.object({
+               baz: v.picklist(['a', 'b'])
+       }),
+       async ({ baz }) => {
+               if (baz === 'a') error(400, 'Nope');
+       }
+);
+
 export const issue_path_form = form(
        v.object({
                nested: v.object({
index 2518529e27d5fe9c6a950c3955887a520aa592fe..3393cf1abdf79b0bd475af85b62d8d756945a8d7 100644 (file)
@@ -1905,6 +1905,33 @@ test.describe('remote functions', () => {
                await expect(allIssues).toContainText('"path":["nested","value"]');
        });
 
+       test('form validation issues cleared', async ({ page, javaScriptEnabled }) => {
+               if (!javaScriptEnabled) return;
+
+               await page.goto('/remote/form/validate');
+
+               const baz = page.locator('input[name="baz"]');
+               const submit = page.locator('#my-form-2 button');
+
+               await baz.fill('c');
+               await submit.click();
+               await expect(page.locator('#my-form-2')).toContainText('Invalid type: Expected');
+
+               await baz.fill('a');
+               await submit.click();
+               await expect(page.locator('#my-form-2')).not.toContainText('Invalid type: Expected');
+               await expect(page.locator('[data-error]')).toHaveText('An error occurred');
+
+               await baz.fill('c');
+               await submit.click();
+               await expect(page.locator('#my-form-2')).toContainText('Invalid type: Expected');
+
+               await baz.fill('b');
+               await submit.click();
+               await expect(page.locator('#my-form-2')).not.toContainText('Invalid type: Expected');
+               await expect(page.locator('[data-error]')).toHaveText('No error');
+       });
+
        test('form inputs excludes underscore-prefixed fields', async ({ page, javaScriptEnabled }) => {
                if (javaScriptEnabled) return;