sveltejs/kit · error

`$` is used to collect all FormData validation issues and ca

Error message

`$` is used to collect all FormData validation issues and cannot be used as the `name` of a form control

What it means

SvelteKit reserves form control names starting with $ (and $., $[) for collecting all FormData validation issues in one place. Using such a name would collide with that internal mechanism, so validate_form_data throws when any FormData key matches /^\$[.[]?/.

Source

Thrown at packages/kit/src/runtime/client/remote-functions/form.svelte.js:832

/**
 * Shallow clone an element, so that we can access e.g. `form.action` without worrying
 * that someone has added an `<input name="action">` (https://github.com/sveltejs/kit/issues/7593)
 * @template {HTMLElement} T
 * @param {T} element
 * @returns {T}
 */
function clone(element) {
	return /** @type {T} */ (HTMLElement.prototype.cloneNode.call(element));
}

/**
 * @param {FormData} form_data
 * @param {string} enctype
 */
function validate_form_data(form_data, enctype) {
	for (const key of form_data.keys()) {
		if (/^\$[.[]?/.test(key)) {
			throw new Error(
				'`$` is used to collect all FormData validation issues and cannot be used as the `name` of a form control'
			);
		}
	}

	if (enctype !== 'multipart/form-data') {
		for (const value of form_data.values()) {
			if (value instanceof File) {
				throw new Error(
					'Your form contains <input type="file"> fields, but is missing the necessary `enctype="multipart/form-data"` attribute. This will lead to inconsistent behavior between enhanced and native forms. For more details, see https://github.com/sveltejs/kit/issues/9819.'
				);
			}
		}
	}
}

View on GitHub (pinned to 03f1687fe6)

Solutions

  1. Rename the control so its name does not start with $ (e.g. $search -> search)
  2. If a $ prefix is required by an external API, transform the FormData in the remote function after removal of the prefix on the client
  3. Adjust server-side expectations to accept the unprefixed name

Example fix

// before
<input name="$query" />
// after
<input name="query" />
Defensive patterns

Strategy: validation

Validate before calling

const RESERVED = /^\$[.[]?/;
function assertNoReservedNames(form) {
  for (const el of form.elements) {
    if (el.name && RESERVED.test(el.name)) throw new Error(`reserved name: ${el.name}`);
  }
}

Prevention

When it happens

Trigger: Submitting a remote form containing a control whose name attribute starts with $, such as name="$search" or name="$.filter", producing a matching FormData key.

Common situations: Naming fields after framework state conventions ($prefixed store-like names); generating names dynamically with a $ prefix; migrating forms from libraries where $ names were meaningful.

Related errors


AI-assisted analysis of sveltejs/kit@03f1687fe6 (2026-09-02). Data as JSON: /api/errors/42b8d77b848dc89b. Report an issue: GitHub.