---
title: "Failed to fetch エラーを解決し、3 つの原因を見分ける"
description: "TypeError: Failed to fetch は、リクエストが HTTP レスポンスを受け取れなかったという意味です。CORS ヘッダーの欠落、停止したサーバー、存在しないホストは、どれも同じこのメッセージになります。"
canonical: "https://logbrew.co/ja/errors/failed-to-fetch"
last_updated: "2026-11-10"
---

# Failed to fetch エラーを解決し、3 つの原因を見分ける

`TypeError: Failed to fetch` は、リクエストが HTTP レスポンスを受け取れなかったという意味です。CORS ヘッダーの欠落、停止したサーバー、存在しないホストは、どれも同じこのメッセージになります。

2026年11月10日 に Chromium 152、@logbrew/browser 0.1.21、@logbrew/sdk 0.1.44 で検証

執筆 [Furkan Erday](https://github.com/furkanerday). Furkan Erday は LogBrew の創業者です。毎日 Claude Code と Codex を使って LogBrew を開発しています。

Canonical: https://logbrew.co/ja/errors/failed-to-fetch

## 失敗した `fetch()` の原因を示すもの

| 何が起きたか | `error.message` | コンソール |
| --- | --- | --- |
| `Access-Control-Allow-Origin` ヘッダーなし | `Failed to fetch` | CORS ポリシー |
| そのポートで何も待ち受けていない | `Failed to fetch` | `ERR_CONNECTION_REFUSED` |
| ホストに DNS レコードがない | `Failed to fetch` | `ERR_NAME_NOT_RESOLVED` |
| サーバーが 500 を返した | 拒否されなかった | `500` |

別のオリジンの API への 4 件のリクエスト。ジョッキがいっぱいなら、そのテキストが原因を示しています。

## どの原因かを突き止める

### ブラウザーのコンソールを開く

`fetch()` は、どのネットワーク障害でも同じ `TypeError: Failed to fetch` で拒否されます。そのすぐ横のコンソール行が、本当の原因を示します。

### API が CORS ヘッダーなしで応答した

コンソールには `blocked by CORS policy` と出ます。サーバーは応答しましたが、ページのオリジンにはレスポンスを読む許可がないため、ブラウザーはその応答を捨てます。

出力

```text
Access to fetch at 'http://127.0.0.1:4874/api/closed' from origin 'http://127.0.0.1:4873' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
```

### そのホストとポートで何も待ち受けていない

コンソールには `net::ERR_CONNECTION_REFUSED` と出ます。API が起動していないか、URL のポートが間違っています。API を起動してから、ポートを確認してください。

出力

```text
Failed to load resource: net::ERR_CONNECTION_REFUSED
```

### ホスト名が解決できない

コンソールには `net::ERR_NAME_NOT_RESOLVED` と出ます。DNS にそのホストのレコードがありません。ホスト名の入力ミスと、このデプロイで API の URL を保持している環境変数を確認してください。

出力

```text
Failed to load resource: net::ERR_NAME_NOT_RESOLVED
```

## コードで解決する

### API から CORS ヘッダーを送る

`Access-Control-Allow-Origin` にページのオリジン、公開 API なら `*` を指定して応答します。テストでは、このヘッダーを追加しただけで、同じエンドポイントが `Failed to fetch` から `HTTP 200` に変わりました。

```bash
Access-Control-Allow-Origin: https://app.example.com
```

### 500 は拒否にならないので、ステータスを確認する

`fetch()` は、404 や 500 を含むどの HTTP 応答でも解決されます。テストでは、本文が `{"error":"tap jammed"}` の 500 が `catch` ではなく `then` の分岐に届きました。本文を読む前に `response.ok` を確認してください。

```bash
const response = await fetch(url);
if (!response.ok) throw new Error(`HTTP ${response.status} for ${url}`);
```

### URL をエラーと一緒に記録する

拒否された `fetch()` にはレスポンスがなく、そのスタックは原因ではなく自分のコードを指します。`fetch()` を呼ぶ場所で捕捉し、メソッドと URL をエラーと一緒に残してください。そうすれば、エラー監視でどのリクエストが失敗したか分かります。

```bash
try {
  return await fetch(url);
} catch (error) {
  console.error("fetch failed", url, error);
  throw error;
}
```

## 実際に試して確認したこと

ページは `http://127.0.0.1:4873` で、`@logbrew/browser` 0.1.21 とその fetch 計装を入れた Chromium 152 で動かしました。`http://127.0.0.1:4874` の API が 3 つのパスに応答し、`catch` なしで 5 件のリクエストを送ったので、各拒否は未処理のリジェクトとして SDK に届きました。

`/api/closed` は CORS ヘッダーなしで 200 を返し、リクエストは `TypeError: Failed to fetch` で拒否されました。何も待ち受けていないポート 4875 へのリクエストと、`http://keg.invalid/api` へのリクエストも、同じエラーで拒否されました。3 つのケースすべてで、`error.message` は `Failed to fetch`、`error.name` は `TypeError` で、スタックは自分たちの `fetch()` 呼び出しを指していました。

コンソールはそれらを区別していました。1 つ目は `blocked by CORS policy`、2 つ目は `net::ERR_CONNECTION_REFUSED`、3 つ目は `net::ERR_NAME_NOT_RESOLVED` でした。ヘッダー付きで 500 を返した `/api/broken` はまったく拒否されず、ヘッダー付きで 200 を返した `/api/open` は `HTTP 200 {"ok":true}` を返しました。

## どの原因でも同じメッセージになる理由

Fetch 仕様は、レスポンス前のあらゆる失敗を 1 つのもの、つまりネットワークエラーにまとめます。これはタイプが `error` でステータスが 0 のレスポンスです。CORS の失敗もその 1 つです。`cors` モードでは、CORS プロトコルを理解しないリソースはネットワークエラーになります。

`fetch()` メソッドは、ネットワークエラーの場合にだけ、Promise を `TypeError` で拒否します。MDN も同じ説明をしています。Promise が拒否されるのは、不正な形式の URL やネットワークエラーなどでリクエストが失敗したときだけで、404 や 504 のような HTTP ステータスでは拒否されません。

MDN の CORS エラーのページには、失敗した CORS リクエストの詳細はセキュリティ上の理由で JavaScript からは取得できず、コンソールが唯一の確認場所だと書かれています。whatwg/fetch#526 は 2017 年からより詳しいエラー型を求めていて、今も開いたままです。

## LogBrew が記録する内容

各拒否は、`Unhandled promise rejection: TypeError` という名前の問題 1 件として届きました。自分たちのバンドル内を指すスタックフレームと、グループ化キー `browser.unhandledrejection:TypeError:/app.js` が付いています。これで分かるのは、どこで `fetch()` を呼んだかであり、何が失敗したかではありません。

fetch 計装は、同じトレースに `browser.fetch GET /api/closed` というスパンを追加しました。ステータス `error`、メソッド、リクエストのパス、`errorType` `TypeError` が付いています。エラーには出ないのに、このスパンは失敗したリクエストを示します。

500 の応答は問題を作らず、ステータス `error` と `statusCode` 500 のスパンだけになりました。200 の応答は、ステータス `ok` のスパンになりました。つまり LogBrew では、500 とネットワーク障害は 2 つの別のスパンになりますが、コードでは後者だけが `catch` に届きます。

## よくある質問

### TypeError Failed to fetch とはどういう意味ですか？

`fetch()` の呼び出しに対して、ブラウザーが HTTP レスポンスを受け取れなかったという意味です。サーバーに到達できない、ホストが解決できない、CORS がレスポンスをブロックした、のいずれかです。3 つのケースでメッセージは同じです。

### Failed to fetch は常に CORS エラーですか？

いいえ。テストでは、CORS ヘッダーの欠落、サーバーのないポート、DNS レコードのないホストのどれもがこのメッセージになりました。原因を示すのは、そのすぐ横のコンソール行だけです。

### fetch が 404 や 500 で拒否しないのはなぜですか？

Fetch 仕様は、ネットワークエラーの場合にだけ拒否します。どのステータスでも HTTP 応答はレスポンスなので、`fetch()` は解決され、`response.ok` は自分で確認します。

### JavaScript で Failed to fetch を捕捉するには？

呼び出しを `try` と `catch` で囲むか、Promise に `.catch()` を付けます。エラーはレスポンスのない `TypeError` なので、URL とメソッドは自分で記録してください。

### Failed to fetch はサーバーが停止しているという意味ですか？

そういう場合もあります。停止したサーバーは、コンソールに `net::ERR_CONNECTION_REFUSED` を出します。同じ `Failed to fetch` は、CORS ヘッダーの欠落や DNS レコードのないホスト名でも発生します。

## どのリクエストが失敗したか、なぜ失敗したかを見る

LogBrew のブラウザー SDK は、各 `fetch()` をメソッド、パス、ステータス付きのスパンとして記録し、そこで発生したエラーと同じトレースに入れます。余裕のある無料プランで始められます。クレジットカードは不要です。

[無料で始める](https://logbrew.co/ja)

## 出典

- [MDN, Window: fetch() method](https://developer.mozilla.org/en-US/docs/Web/API/Window/fetch)
- [MDN, CORS errors](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/CORS/Errors)
- [Fetch Standard, The fetch() method](https://fetch.spec.whatwg.org/#fetch-method)
- [whatwg/fetch#526](https://github.com/whatwg/fetch/issues/526)

## ほかの JavaScript エラーの解決方法

- [メッセージ、ファイル、行を隠す Script error を解決する](https://logbrew.co/ja/errors/script-error)
- [再現した JavaScript エラーとそれぞれの解決方法](https://logbrew.co/ja/errors)
