---
type: reference
language: javascript
slug: error/error
title: "Error と try / catch / finally / throw"
title_tag: "JavaScript の例外 — Error と try/catch の使い方"
summary: >
  Error が持っているもの、throw できるもの、finally が必ず動くこと、JSON にすると空になる理由、
  cause で原因を繋ぐ書き方、独自のエラーを作って種類で分ける方法までを実行して確かめます。
description: >
  JSON.stringify(new Error()) は {} になります。ログに出したつもりで消えるのはこれが原因です。
  finally が return より後に動くこと、cause で原因を繋ぐ書き方まで実行して確かめられます。
status: published
difficulty: 2
minutes: 10

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

sources:
  - title: "Error Objects — ECMAScript® 2026 Language Specification"
    url: "https://tc39.es/ecma262/#sec-error-objects"
  - title: "The try Statement — ECMAScript® 2026 Language Specification"
    url: "https://tc39.es/ecma262/#sec-try-statement"
  - title: "Error.prototype.cause — MDN"
    url: "https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Error/cause"

terms: [例外, 送出, 捕捉, スタックトレース, 原因]

links:
  related:
    - javascript/errors/is-not-a-function
    - javascript/how-to/async/retry
    - javascript/reference/json/parse

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

`Error` が持っているのは、**種類・文言・スタックトレース**の3つです。

```js run
const error = new Error('壊れた');

console.log(error.name);
console.log(error.message);
console.log(String(error));
console.log(typeof error.stack);
```
```output
Error
壊れた
Error: 壊れた
string
```

`name` と `message` を `:` で繋いだものが、文字列にしたときの形です。

## 組み込みの種類

```js run
for (const Kind of [TypeError, RangeError, SyntaxError, ReferenceError]) {
  const error = new Kind('x');
  console.log(error.name, error instanceof Error);
}
```
```output
TypeError true
RangeError true
SyntaxError true
ReferenceError true
```

**すべて `Error` を継承しています。** だから `instanceof Error` で一括して受けられます。

よく出る2つは、それぞれ独立したページで扱っています。
→ [TypeError: x is not a function](/ja/javascript/errors/is-not-a-function/)
→ [SyntaxError: Unexpected token](/ja/javascript/errors/unexpected-token/)

| 種類 | いつ出るか |
|---|---|
| `TypeError` | 型が合わない（関数でないものを呼んだ、`null` の中身を読んだ） |
| `RangeError` | 値が範囲の外（配列の長さ、`toFixed` の桁） |
| `ReferenceError` | 名前が見つからない |
| `SyntaxError` | 構文として読めない（`JSON.parse` を含む） |

## `throw` できるものは何でも

```js run
for (const value of [new Error('e'), '文字列', 42]) {
  try {
    throw value;
  } catch (caught) {
    console.log(typeof caught, caught instanceof Error);
  }
}
```
```output
object true
string false
number false
```

**文字列も数値も投げられます。ですが投げないでください。**

`Error` でないものを投げると、`message` も `stack` も付きません。
受け取った側は[bad:何が起きたか調べられません]。

```js run
function risky(useError) {
  throw useError ? new Error('理由が分かる') : '理由だけ';
}

for (const useError of [true, false]) {
  try {
    risky(useError);
  } catch (error) {
    console.log(error?.message ?? '(message が無い)', '|', typeof error?.stack);
  }
}
```
```output
理由が分かる | string
(message が無い) | undefined
```

## `finally` は必ず動く

```js run
function run(fail) {
  try {
    if (fail) throw new Error('だめ');
    return '成功';
  } catch (error) {
    return '失敗';
  } finally {
    console.log('finally');
  }
}

console.log(run(false));
console.log(run(true));
```
```output
finally
成功
finally
失敗
```

**`return` より後に動きます。** 後始末（閉じる・解放する・止める）を書く場所です。

[bad:`finally` の中で `return` すると、`try` や `catch` の結果を上書きします。]
書かないでください。

## 使わない引数は省ける

```js run
try {
  JSON.parse('x');
} catch {
  console.log('中身を見ないなら省略できる');
}
```
```output
中身を見ないなら省略できる
```

## JSON にすると空になる

**これがいちばん事故になります。**

```js bad
const error = new Error('壊れた');

console.log(JSON.stringify(error));
console.log(Object.keys(error));
```
```output
{}
[]
```

`name` も `message` も `stack` も、**列挙されないので消えます。**

ログに送ったつもりで `{}` だけが残る、というのはこれが原因です。
**自分で取り出してください。**

```js run
function toLog(error) {
  return {
    name: error.name,
    message: error.message,
    stack: typeof error.stack === 'string' ? error.stack.split('\n')[0] : null,
  };
}

console.log(JSON.stringify(toLog(new Error('壊れた'))));
```
```output
{"name":"Error","message":"壊れた","stack":"Error: 壊れた"}
```

→ [JSON.parse() と JSON.stringify()](/ja/javascript/reference/json/parse/)

## 原因を繋ぐ

`cause` で、**元の失敗を保ったまま**包み直せます（ES2022）。

```js run
const low = new Error('通信できない');
const high = new Error('ユーザーの取得に失敗', { cause: low });

console.log(high.message);
console.log(high.cause.message);
```
```output
ユーザーの取得に失敗
通信できない
```

**握りつぶさずに、文脈だけを足せます。**

```js bad
try {
  JSON.parse('x');
} catch (error) {
  throw new Error('設定を読めません');
}
```

これだと[bad:元の `SyntaxError` が消えます]。`cause` を付けてください。

## 独自のエラーを作る

**種類で分けたいときに作ります。**

```js run
class NotFoundError extends Error {
  constructor(id) {
    super(`見つかりません: ${id}`);
    this.name = 'NotFoundError';
    this.id = id;
  }
}

const error = new NotFoundError(7);

console.log(error.name, error.message, error.id);
console.log(error instanceof NotFoundError, error instanceof Error);
```
```output
NotFoundError 見つかりません: 7 7
true true
```

`super(message)` を呼び、`name` を自分で入れます。
→ [class — 作る・継承する・隠す](/ja/javascript/reference/class/class/)

**受け取る側は種類で分けられます。**

```js run
class NotFoundError extends Error {
  constructor(id) {
    super(`見つかりません: ${id}`);
    this.name = 'NotFoundError';
  }
}

function handle(error) {
  if (error instanceof NotFoundError) return '404 として扱う';
  if (error instanceof TypeError) return 'こちらの不具合';
  return '不明';
}

console.log(handle(new NotFoundError(1)));
console.log(handle(new TypeError('x')));
console.log(handle(new Error('x')));
```
```output
404 として扱う
こちらの不具合
不明
```

[em:文言で分岐しないでください。] 文言は処理系や版で変わります。
**種類（`instanceof`）か、自分で付けた印（`code` など）で分けます。**

## よくある間違い

### 何でも `catch` して握りつぶす

```js bad
try {
  JSON.parse('x');
} catch {
  // 何もしない
}
```

**問題が消えたのではなく、見えなくなっただけ**です。
記録するか、包んで投げ直すか、どちらかにしてください。

### 想定外まで受けてしまう

```js run
function parse(text) {
  try {
    return JSON.parse(text);
  } catch (error) {
    if (error instanceof SyntaxError) return null;
    throw error;
  }
}

console.log(parse('{"a":1}'));
console.log(parse('x'));
```
```output
{ a: 1 }
null
```

**受けたい種類だけ受け、それ以外は投げ直す。**
そうしないと、想定外の不具合まで `null` に化けます。

失敗したときにやり直す形は、こちらにまとめています。
→ [失敗したら再試行する](/ja/javascript/how-to/async/retry/)

### `try` の範囲が広すぎる

`try` に何十行も入れると、**どこで失敗したのか分からなくなります。**
落ちうる1行だけを囲んでください。

## まとめ

- `Error` が持つのは[key:種類・文言・スタックトレース]
- 組み込みの種類はすべて `Error` を継承している
- **`Error` 以外を投げない。** `message` も `stack` も付かない
- `finally` は `return` より後に動く。**中で `return` しない**
- **`JSON.stringify(error)` は `{}`。** 自分で取り出す
- 包み直すときは `cause` で元を残す
- 分岐は[em:文言ではなく種類]で
