# A “script” element with a “defer” attribute must not have a “type” attribute with the value “module”.

> Canonical HTML version: https://rocketvalidator.com/html-validation/a-script-element-with-a-defer-attribute-must-not-have-a-type-attribute-with-the-value-module
> Attribution: Rocket Validator (https://rocketvalidator.com)
> License: CC BY 4.0 (https://creativecommons.org/licenses/by/4.0/)

The HTML living standard defines that scripts with `type="module"` are always fetched in parallel and evaluated after the document has been parsed, which is the same behavior that the `defer` attribute provides for classic scripts. Because this deferred execution is an inherent characteristic of module scripts, the spec explicitly forbids combining the two. Including both doesn't change how the browser handles the script, but it signals a misunderstanding of how modules work and produces invalid HTML.

This validation error commonly arises when developers migrate classic scripts to ES modules. A classic script like `<script defer src="app.js"></script>` relies on the `defer` attribute to avoid blocking the parser. When converting to a module by adding `type="module"`, it's natural to leave `defer` in place — but it's no longer needed or allowed.

It's worth noting that the `async` attribute *is* valid on module scripts and does change their behavior. While `defer` is redundant because modules are already deferred, `async` overrides that default and causes the module to execute as soon as it and its dependencies have finished loading, rather than waiting for HTML parsing to complete.

## How to Fix

Remove the `defer` attribute from any `<script>` element that has `type="module"`. No other changes are needed — the loading and execution behavior will remain identical.

If you intentionally want the script to run as soon as possible (before parsing completes), use `async` instead of `defer`. But if you want the standard deferred behavior, simply omit both attributes and let the module default take effect.

## Examples

### ❌ Incorrect: `defer` combined with `type="module"`

```html
<script type="module" defer src="app.js"></script>
```

The `defer` attribute is redundant here and causes a validation error.

### ✅ Correct: module script without `defer`

```html
<script type="module" src="app.js"></script>
```

Module scripts are deferred automatically, so this behaves exactly the same as the incorrect example above but is valid HTML.

### ✅ Correct: using `async` with a module (when needed)

```html
<script type="module" async src="analytics.js"></script>
```

Unlike `defer`, the `async` attribute is permitted on module scripts. It causes the module to execute as soon as it's ready, without waiting for HTML parsing to finish.

### ✅ Correct: classic script with `defer`

```html
<script defer src="app.js"></script>
```

For classic (non-module) scripts, the `defer` attribute is valid and necessary if you want deferred execution.
