---
type: errors
language: javascript
slug: await-is-only-valid-in-async
title: "SyntaxError: await is only valid in async functions"
title_tag: "await is only valid in async functions の原因と直し方"
summary: >
  await を書ける場所は決まっています。async を付け忘れた関数、コールバックの中、
  昔の書き方のファイル。それぞれの直し方と、直った後に起きやすい間違いまで載せています。
description: >
  await は async を付けた関数の中でしか書けません。forEach のコールバックで出る理由、
  直した後に await を付け忘れて Promise がそのまま流れる問題まで実行して確かめられます。
status: published
difficulty: 2
minutes: 8

versions:
  verified: "Node 22.22.3"
  since: "ES2017"
  deprecated: null
  removed: null

sources:
  - title: "Async Function Definitions — ECMAScript® 2026 Language Specification"
    url: "https://tc39.es/ecma262/#sec-async-function-definitions"
  - title: "Await — ECMAScript® 2026 Language Specification"
    url: "https://tc39.es/ecma262/#await"
  - title: "await — MDN"
    url: "https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/await"

terms: [非同期関数, 構文エラー, トップレベル await]

links:
  related:
    - javascript/reference/promise/promise
    - javascript/how-to/async/parallel
    - javascript/reference/timer/set-timeout
    - javascript/learn/array/loop

content_updated_at: 2026-09-08
published_at: 2026-09-08
---

`await` を書ける場所は**決まっています。**

```js run
try {
  new Function('return await Promise.resolve(1);');
} catch (error) {
  console.log(error.name + ': ' + error.message);
}
```
```output
SyntaxError: await is only valid in async functions and the top level bodies of modules
```

**実行する前に弾かれます。** 1行も動きません。

[dim:ここでは文言を見せるために `new Function()` を使っています。ふつうに書いた場合は、ファイルを読み込んだ時点で止まります。]

## 書ける場所

| 場所 | 書けるか |
|---|---|
| `async` を付けた関数の中 | **書ける** |
| モジュールの一番外側 | **書ける**（ES2022） |
| `async` の無い関数の中 | [bad:書けない] |
| コールバックの中（そのコールバックに `async` が無い） | [bad:書けない] |
| モジュールでないファイルの一番外側 | [bad:書けない] |

## 原因1: `async` の付け忘れ

**いちばん多い原因です。**

```js
function load() {
  return await fetch('/api');
}
```

`async` を付けます。

```js run
async function load() {
  return await Promise.resolve('読み込んだ');
}

console.log(await load());
```
```output
読み込んだ
```

アロー関数も同じです。**`async` は矢印の前**に書きます。

```js run
const load = async () => await Promise.resolve('読み込んだ');

console.log(await load());
```
```output
読み込んだ
```

オブジェクトのメソッドとクラスのメソッドは、**名前の前**に書きます。

```js run
const api = {
  async load() {
    return await Promise.resolve('メソッド');
  },
};

class Client {
  async load() {
    return await Promise.resolve('クラス');
  }
}

console.log(await api.load());
console.log(await new Client().load());
```
```output
メソッド
クラス
```

## 原因2: コールバックの中に書いた

**外側に `async` があっても、届きません。**

```js
async function main() {
  [1, 2].forEach(function (n) {
    await save(n);
  });
}
```

`await` があるのは `function (n)` の中で、そこには `async` がありません。

[bad:ここで内側のコールバックに `async` を付けるのは、たいてい間違いです。]

```js run
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
const order = [];

[1, 2].forEach(async (n) => {
  await sleep(1);
  order.push(n);
});

order.push('forEach を抜けた');

await sleep(30);

console.log(order.join(' -> '));
```
```output
forEach を抜けた -> 1 -> 2
```

**構文の誤りは消えますが、待ってくれません。**
`forEach()` はコールバックが返した `Promise` を見ないからです。

`for...of` に替えてください。

```js run
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
const order = [];

for (const n of [1, 2]) {
  await sleep(1);
  order.push(n);
}

order.push('for...of を抜けた');

console.log(order.join(' -> '));
```
```output
1 -> 2 -> for...of を抜けた
```

**同時に走らせてよいなら `map()` と `Promise.all()`** です。

```js run
const double = async (n) => n * 2;

console.log(await Promise.all([1, 2].map(double)));
```
```output
[ 2, 4 ]
```

→ [複数の非同期処理を同時に走らせる](/ja/javascript/how-to/async/parallel/)

## 原因3: モジュールとして読まれていない

文言の後半にある「the top level bodies of modules」がこれです。

**モジュールなら、関数の外側でも `await` を書けます。**

- `<script type="module">` で読み込む
- 拡張子を `.mjs` にする、または `package.json` に `"type": "module"` を書く

`import` / `export` が使えない環境なら、**囲って呼びます。**

```js run
async function main() {
  return await Promise.resolve('囲んだ');
}

main().then((value) => console.log(value));

await new Promise((resolve) => setTimeout(resolve, 10));
```
```output
囲んだ
```

[dim:このページの実行パネルは中身を非同期の関数として扱うので、一番外側の `await` がそのまま動きます。自分のファイルでも同じとは限りません。]

## 直った後に起きやすい間違い

### `await` を付け忘れる

**こちらは構文エラーになりません。静かに壊れます。**

```js bad
async function get() {
  return { name: 'あ' };
}

const user = get();

console.log(user);
console.log(user.name);
```
```output
Promise {}
undefined
```

`async` を付けた関数は、[key:必ず Promise を返します]。
`await` を付けないと、中身ではなく**入れ物**が返ります。

```js run
async function get() {
  return { name: 'あ' };
}

const user = await get();

console.log(user.name);
```
```output
あ
```

[em:`undefined` が出たら、まず `await` の付け忘れを疑ってください。]

### 失敗を受け止めない

```js run
async function fail() {
  throw new Error('だめ');
}

try {
  await fail();
} catch (error) {
  console.log('catch:', error.message);
}
```
```output
catch: だめ
```

`await` を付けていれば、**ふつうの `try` / `catch` で受けられます。**
付けていないと、`try` の外に抜けてしまいます。
→ [Error と try / catch / finally / throw](/ja/javascript/reference/error/error/)

## 探しかたの順序

1. `await` を書いた行から、**いちばん近い関数**を探す
2. その関数に `async` が付いているか見る
   - 付いていない → 付ける
   - **その関数がコールバックだった** → `for...of` に替えるか、`Promise.all()` にする
3. 関数の外側なら、そのファイルが**モジュールとして読まれているか**確かめる
4. 直ったら、`await` の付け忘れが無いか見直す

[dim:このページの実行結果は Node 22.22.3 のものです。文言は処理系と版によって変わります。]

## まとめ

- `await` は[key:async を付けた関数の中]と[key:モジュールの一番外側]だけ
- **外側に `async` があっても、コールバックの中には届かない**
- `forEach()` に `async` を付けても[bad:待ってくれない]。`for...of` か `Promise.all()`
- 順番に待つなら `for...of`、同時でよいなら `map()` と `Promise.all()`
- 直った後は **`await` の付け忘れ**に注意。`undefined` が出たらまずそこ
