# Element “script” must not have attribute “async” unless attribute “src” is also specified or unless attribute “type” is specified with value “module”.

> Canonical HTML version: https://rocketvalidator.com/html-validation/element-script-must-not-have-attribute-async-unless-attribute-src-is-also-specified-or-unless-attribute-type-is-specified-with-value-module
> Attribution: Rocket Validator (https://rocketvalidator.com)
> License: CC BY 4.0 (https://creativecommons.org/licenses/by/4.0/)

The `async` attribute tells the browser to download and execute a script without blocking HTML parsing. For external scripts (those with a `src` attribute), this means the browser can continue parsing the page while fetching the file, then execute the script as soon as it's available. For inline module scripts (`type="module"`), `async` changes how the module's dependency graph is handled — the module and its imports execute as soon as they're all ready, rather than waiting for HTML parsing to complete.

For a classic inline script (no `src`, no `type="module"`), there is nothing to download asynchronously. The browser encounters the code directly in the HTML and executes it immediately. Applying `async` in this context is meaningless and contradicts the HTML specification, which is why the W3C validator flags it as an error.

Beyond standards compliance, using `async` incorrectly can signal a misunderstanding of script loading behavior, which may lead to bugs. For example, a developer might mistakenly believe that `async` on an inline script will defer its execution, when in reality it has no effect and the script still runs synchronously during parsing.

## How to Fix

You have several options depending on your intent:

1. **If the script should be external**, move the code to a separate file and reference it with the `src` attribute alongside `async`.
2. **If the script should be an inline module**, add `type="module"` to the `<script>` tag. Note that module scripts are deferred by default, and `async` makes them execute as soon as their dependencies are resolved rather than waiting for parsing to finish.
3. **If the script is a plain inline script**, simply remove the `async` attribute — it has no practical effect anyway.

## Examples

### ❌ Invalid: `async` on a classic inline script

```html
<script async>
  console.log("Hello, world!");
</script>
```

This triggers the validator error because there is no `src` attribute and the `type` is not `"module"`.

### ✅ Fixed: Remove `async` from the inline script

```html
<script>
  console.log("Hello, world!");
</script>
```

### ✅ Fixed: Use `async` with an external script

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

The `async` attribute is valid here because the browser needs to fetch `app.js` from the server, and `async` controls when that downloaded script executes relative to parsing.

### ✅ Fixed: Use `async` with an inline module

```html
<script async type="module">
  import { greet } from "./utils.js";
  greet();
</script>
```

This is valid because module scripts have a dependency resolution phase that can happen asynchronously. The `async` attribute tells the browser to execute the module as soon as all its imports are resolved, without waiting for the document to finish parsing.

### ❌ Invalid: `async` with `type="text/javascript"` (not a module)

```html
<script async type="text/javascript">
  console.log("This is still invalid.");
</script>
```

Even though `type` is specified, only `type="module"` satisfies the requirement. The value `"text/javascript"` is the default classic script type and does not make `async` valid on an inline script.
