- JavaScript
Failed to fetchの原因と直し方|fetchエラー
TypeError: Failed to fetch は、fetch が応答を受け取れなかった(またはブラウザーが応答を渡さなかった)ときのエラーです。 メッセージは原因によらず同じなので、Console の「1行上」や Network タブを見て原因を見分けます。
| Console に一緒に出る表示 | 原因 | 直す場所 |
|---|---|---|
net::ERR_CONNECTION_REFUSED |
サーバーが動いていない・ポートが違う | サーバー・URL |
net::ERR_NAME_NOT_RESOLVED |
ホスト名が引けない(DNS) | URL・DNS |
has been blocked by CORS policy |
CORS(別のオリジンへのアクセスをサーバーが許可していない) | API サーバーの応答ヘッダー |
net::ERR_CERT_AUTHORITY_INVALID など |
HTTPS の証明書を信頼できない | サーバーの証明書 |
Mixed Content: ... This request has been blocked |
HTTPS のページから HTTP の API を呼んだ | API を HTTPS に |
Uncaught (in promise) は、エラーを catch していないという印です。原因そのものではありません。
確認環境:Chromium 141(Playwright)、Node.js 22.22.2(確認日 2026年10月10日)。ページを http://app.test:18081、API を http://api.test:18082 の別オリジンにして、9つのパターンを再現しました。
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「Failed to fetchの原因と直し方|fetchエラー」
再現した結果の一覧
| # | 状況 | fetch の結果 | Console・Network の表示 |
|---|---|---|---|
| 1 | API サーバーが止まっている | Failed to fetch | net::ERR_CONNECTION_REFUSED |
| 2 | 存在しないホスト名 | Failed to fetch | net::ERR_NAME_NOT_RESOLVED |
| 3 | API が CORS のヘッダーを返さない | Failed to fetch | No 'Access-Control-Allow-Origin' header is present |
| 4 | JSON の POST で、プリフライトに応えない | Failed to fetch | Response to preflight request doesn't pass access control check |
| 5 | credentials: 'include' で、* を返している |
Failed to fetch | must not be the wildcard '*' when the request's credentials mode is 'include' |
| 6 | 500 エラーの応答に CORS のヘッダーが無い | Failed to fetch | No 'Access-Control-Allow-Origin' header(中身は500) |
| 7 | 信頼されていない証明書の HTTPS | Failed to fetch | net::ERR_CERT_AUTHORITY_INVALID |
| 8 | HTTPS のページから HTTP の API | Failed to fetch | Mixed Content: ... This request has been blocked |
| 9 | タイムアウト(AbortSignal.timeout) |
TimeoutError: signal timed out |
net::ERR_ABORTED |
比較のため、エラーにならなかったものも並べます。
| 状況 | fetch の結果 |
|---|---|
CORS のヘッダーあり(Access-Control-Allow-Origin: *) |
status=200 ok=true |
| 500 エラー(CORS のヘッダーあり) | status=500 ok=false(例外にならない) |
| 同じオリジンへの fetch | status=200 ok=true |
fetch は、HTTP の 404 や 500 では例外になりません(MDN にも記載があります)。Failed to fetch が出たら、応答そのものが受け取れていないと考えます。応答は返ってきたが中身が JSON でない場合は、Unexpected token '<' という別のエラーになります。
見分け方:Console の「すぐ上」を読む
Access to fetch at 'http://api.test:18082/nocors' from origin 'http://app.test:18081'
has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
Failed to load resource: net::ERR_FAILED
Uncaught (in promise) TypeError: Failed to fetch
一番下の Failed to fetch だけを見ても原因は分かりません。上の行に、ブラウザーが止めた理由が出ています。Network タブでは、該当のリクエストの Status 列に、失敗したことと理由が表示されます。
| 確認する場所 | 分かること |
|---|---|
| Console(エラーの上の行) | CORS・Mixed Content など、ブラウザーが止めた理由 |
| Network タブの Status | 失敗したリクエストと、その理由 |
Network タブで OPTIONS のリクエスト |
プリフライト(下で説明)の応答 |
| サーバーのログ | リクエストがサーバーに届いたかどうか |
原因1・2:サーバーに届いていない
API サーバーが止まっている、ポートが違う、ホスト名を打ち間違えている、のどれかです。
| 確認すること | 方法 |
|---|---|
| サーバーが動いているか | ブラウザーで API の URL を直接開く、curl -i URL |
| URL のポート・ホスト名 | 開発時の localhost:3000 と localhost:8080 の取り違え |
| 本番で環境変数が入っているか | undefined/api/users のような URL になっていないか |
原因3〜6:CORS(いちばん多い)
ページのオリジン(スキーム://ホスト:ポート)と、API のオリジンが違うと、API が「このオリジンからなら使ってよい」と応答ヘッダーで許可しない限り、ブラウザーは応答を JavaScript に渡しません。
3. 応答に Access-Control-Allow-Origin が無い
CORS のエラーでも、リクエストはサーバーに届いています。 確認環境のサーバーのログには GET /nocors 200 と記録されていました。サーバーは正常に応答しており、ブラウザーが JavaScript に渡さなかっただけです。そのため、直す場所はフロントエンドではなく、API サーバーの応答ヘッダーです。
Access-Control-Allow-Origin: http://app.test:18081 ← ページのオリジン(または *)
4. JSON の POST は、先に OPTIONS(プリフライト)が飛ぶ
Content-Type: application/json の POST や、Authorization ヘッダーを付けたリクエストでは、ブラウザーは本番のリクエストの前に、OPTIONS で「送ってよいか」を確認します(プリフライト)。確認環境では、サーバーのログに OPTIONS /cors-star 404 だけが残り、POST は送られていませんでした。
OPTIONS への応答に必要なヘッダーの例
Access-Control-Allow-Origin: http://app.test:18081
Access-Control-Allow-Methods: GET, POST
Access-Control-Allow-Headers: Content-Type, Authorization
OPTIONS に上のヘッダーを返すようにすると、POST まで通りました(status=200)。
5. Cookie を送るなら、* は使えない
credentials: 'include'(Cookie を送る)のときは、Access-Control-Allow-Origin: * ではブロックされました。オリジンを具体的に書いても、Access-Control-Allow-Credentials が無いと The value of the 'Access-Control-Allow-Credentials' header in the response is '' which must be 'true' でブロックされました。オリジンを具体的に書き、Access-Control-Allow-Credentials: true も返すと通りました(status=200)。
6. 500 エラーのときだけ CORS のヘッダーが付いていない
確認環境で、サーバーが 500 を返し、その応答に CORS のヘッダーが無いと、JavaScript からは Failed to fetch、Console には CORS のエラーが出ました。サーバーのログには 500 が記録されています。
Console : has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header ...
Server : "GET /err500-nocors HTTP/1.1" 500
普段は動くのに、ときどき CORS のエラーになる場合は、このパターンを疑います。CORS のヘッダーを、正常な応答だけでなく、エラーの応答(例外ハンドラーが返す応答)にも付ける設定にします。原因の 500 は、サーバーのログで確かめます。
mode: 'no-cors' では直らない
fetch(url, { mode: 'no-cors' }) → status=0 ok=false type=opaque
エラーは消えますが、応答の中身は読めません(type=opaque)。CORS を回避する方法ではありません。
開発中なら、開発サーバーのプロキシで同じオリジンにする
Vite(server.proxy)や webpack-dev-server の proxy で /api を API サーバーに転送すると、ブラウザーから見て同じオリジンになり、CORS の確認そのものが不要になります。確認環境でも、同じオリジンへの fetch は status=200 でした。本番では、同じドメインに配置するか、API サーバーで CORS を設定します。
原因7:証明書のエラー
自己署名の証明書や、信頼されていない認証局の証明書を使った HTTPS の API では、net::ERR_CERT_AUTHORITY_INVALID で失敗しました。ブラウザーで API の URL を直接開くと、警告の画面で理由が分かります。正しい証明書をサーバーに設定するのが直し方です。
原因8:混在コンテンツ(HTTPS のページから HTTP の API)
Mixed Content: The page at 'https://app.test:18443/page' was loaded over HTTPS,
but requested an insecure resource 'http://api.test:18082/cors-star'.
This request has been blocked; the content must be served over HTTPS.
HTTPS のページから http:// の API は呼べません。 ローカルでは動いて、本番(HTTPS)にしたら失敗する、というときに多い原因です。API も HTTPS にして、URL を https:// にします。
原因9(似たエラー):タイムアウトと中断
AbortSignal.timeout(ミリ秒) で時間切れにすると、TimeoutError: signal timed out になり、Failed to fetch とは区別できました。AbortController で中断した場合は AbortError です。
catch して、原因が分かる形で扱う
async function fetchJson(url, options = {}) {
let res;
try {
res = await fetch(url, { signal: AbortSignal.timeout(10000), ...options });
} catch (e) {
if (e.name === 'TimeoutError') throw new Error(`時間切れ: ${url}`);
// TypeError: Failed to fetch … 原因は Console・Network タブで確認
throw new Error(`通信できません(サーバー停止・CORS・証明書・混在コンテンツ): ${url}`, { cause: e });
}
if (!res.ok) throw new Error(`HTTP ${res.status}: ${url}`); // 404・500 は例外にならないので自分で判定
return res.json();
}
JavaScript からは、CORS なのかサーバー停止なのかを区別できません(どれも同じ TypeError)。画面には「通信できませんでした」と出し、原因は開発者ツールとサーバーのログで調べます。
Node.js では「fetch failed」
サーバー側(Node.js・Next.js のサーバーコンポーネントなど)の fetch では、メッセージが fetch failed になり、cause に原因が入っています。CORS はブラウザーの仕組みなので、Node.js では起きません。
TypeError: fetch failed | cause: ECONNREFUSED connect ECONNREFUSED 127.0.0.1:18099
TypeError: fetch failed | cause: ENOTFOUND getaddrinfo ENOTFOUND no-such-host.invalid
try { await fetch(url); }
catch (e) { console.error(e.message, e.cause?.code); } // cause.code を必ず出す
確認の手順(チェックリスト)
| 順番 | 確認すること | 方法 |
|---|---|---|
| 1 | Console のエラーの上の行 | CORS・Mixed Content・net::ERR_... |
| 2 | Network タブ | 失敗したリクエスト、OPTIONS の応答 |
| 3 | サーバーに届いたか | サーバーのログ。届いていれば CORS か 500 のヘッダー漏れ |
| 4 | URL | ポート・ホスト名・https:// か |
| 5 | エラー時の応答にも CORS のヘッダーがあるか | 500 を起こして確かめる |
| 6 | Node.js なら | e.cause.code |
よくある質問
Q. Postman や curl では動くのに、ブラウザーだけ Failed to fetch になります。
A. CORS の可能性が高いです。CORS はブラウザーだけが行う確認なので、Postman や curl では起きません。Console に blocked by CORS policy が出ていないかを見ます。
Q. フロントエンドのコードで CORS を直せますか。
A. 直せません。許可するのは API サーバーの応答ヘッダーです。mode: 'no-cors' はエラーが消えるだけで、中身は読めません。開発中なら開発サーバーのプロキシで同じオリジンにする方法があります。
Q. 自分のパソコンだけで起きます。 A. 広告ブロックなどのブラウザー拡張機能が、リクエストを止めていることがあります。シークレットウィンドウ(拡張機能が無効の状態)で試すと切り分けられます。
まとめ
Failed to fetchは応答を受け取れなかったという意味。原因は Console の上の行と Network タブで見る- CORS のエラーでも、リクエストはサーバーに届いている。直すのは API サーバーの応答ヘッダー
- JSON の POST はプリフライト(OPTIONS)に応える必要がある。Cookie を送るなら
*は使えない - 500 の応答に CORS のヘッダーが無いと、CORS のエラーに見える
- HTTPS のページから HTTP の API は呼べない(混在コンテンツ)
- 404・500 では fetch は例外にならない。
res.okを自分で判定する - Node.js では
fetch failed。原因はcauseに入っている
参考・出典
確認日はいずれも 2026年10月10日です。
- MDN Web Docs「Window: fetch() method」:https://developer.mozilla.org/en-US/docs/Web/API/Window/fetch
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「Failed to fetchの原因と直し方|fetchエラー」
株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。
WE ARE HIRING
RJCで一緒に開発しながら、
成長を楽しみませんか?
RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!
- 127日年間休日
- 12時間平均残業時間
- 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!
ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。