# Bad value “X” for attribute “novalidate” on element “form”.

> Canonical HTML version: https://rocketvalidator.com/html-validation/bad-value-x-for-attribute-novalidate-on-element-form
> Attribution: Rocket Validator (https://rocketvalidator.com)
> License: CC BY 4.0 (https://creativecommons.org/licenses/by/4.0/)

## Understanding Boolean Attributes in HTML

In HTML, boolean attributes work differently from regular attributes. A boolean attribute's presence on an element represents `true`, and its absence represents `false`. According to the [HTML specification](https://html.spec.whatwg.org/multipage/common-microsyntax.html#boolean-attributes), a boolean attribute may only have three valid forms:

- The attribute name alone: `novalidate`
- The attribute with an empty value: `novalidate=""`
- The attribute with a value matching its own name (case-insensitive): `novalidate="novalidate"`

Any other value — such as `"true"`, `"false"`, `"1"`, `"0"`, or `"yes"` — is invalid and triggers this validation error. This is a common source of confusion, especially for developers coming from frameworks like React (which uses `noValidate={true}`) or from languages where boolean attributes accept explicit `true`/`false` strings.

## Why This Matters

- **Standards compliance:** Using invalid values violates the HTML specification and will cause W3C validation failures.
- **Unexpected behavior:** While most browsers are lenient and treat any value of `novalidate` as "present" (meaning even `novalidate="false"` would *disable* validation, not enable it), relying on this behavior is unreliable and misleading to other developers reading your code.
- **Maintainability:** Writing `novalidate="false"` suggests the form *should* be validated, but the opposite is true — the attribute is present, so validation is skipped. This creates confusing, error-prone code.

## About the `novalidate` Attribute

The `novalidate` attribute tells the browser to skip its built-in constraint validation when the form is submitted. Without it, the browser checks required fields, input patterns, email formats, and other constraints before allowing submission.

If `novalidate` is not set on the form, individual submit buttons can still bypass validation on a per-button basis using the `formnovalidate` attribute on a `<button>`, `<input type="submit">`, or `<input type="image">` element.

## Examples

### ❌ Invalid: Arbitrary value on `novalidate`

```html
<form method="post" novalidate="true">
  <label>Email:
    <input type="email" name="email" required>
  </label>
  <button>Submit</button>
</form>
```

This triggers the error because `"true"` is not a valid value for a boolean attribute. Other invalid variations include:

```html
<form method="post" novalidate="1">
<form method="post" novalidate="yes">
<form method="post" novalidate="false">
```

Note that `novalidate="false"` is especially dangerous — it does **not** enable validation. Because the attribute is present, the browser disables validation regardless of the value.

### ✅ Valid: Attribute name alone (recommended)

```html
<form method="post" novalidate>
  <label>Email:
    <input type="email" name="email" required>
  </label>
  <button>Submit</button>
</form>
```

### ✅ Valid: Empty string value

```html
<form method="post" novalidate="">
  <label>Email:
    <input type="email" name="email" required>
  </label>
  <button>Submit</button>
</form>
```

### ✅ Valid: Value matching the attribute name

```html
<form method="post" novalidate="novalidate">
  <label>Email:
    <input type="email" name="email" required>
  </label>
  <button>Submit</button>
</form>
```

### ✅ Valid: Removing the attribute to enable validation

If you want the form to be validated, simply remove the `novalidate` attribute entirely:

```html
<form method="post">
  <label>Email:
    <input type="email" name="email" required>
  </label>
  <button>Submit</button>
</form>
```

### ✅ Using `formnovalidate` on a specific button

If you want validation on the primary submit but want to skip it for a "Save Draft" button, use `formnovalidate` on the button instead:

```html
<form method="post">
  <label>Email:
    <input type="email" name="email" required>
  </label>
  <button>Submit</button>
  <button formnovalidate>Save Draft</button>
</form>
```

This pattern keeps validation active for the main submission while allowing drafts to bypass it — without needing `novalidate` on the form at all.
