Uncaught (in promise) Error: ... は、Promise(非同期の処理)が失敗(reject)したのに、その失敗を受け取る処理(catch)がどこにも無かったときに、ブラウザのコンソールに出るエラーです。 in promise の後ろに、元のエラー(TypeError: Cannot read properties of undefined など)が続きます。

直し方は、失敗を受け取る場所を作ることです。

書いたもの 直し方
async の関数を await せずに呼んだ await を付け、try/catch で囲む
promise.then(...) だけで、catch が無い 最後に .catch(...) を付ける
forEach(async ...) for...of と await、または Promise.all
fetch のあと、r.json() で失敗 r.ok を確かめてから json()

確認環境:Chromium 141、Node.js 22.22.2(確認日 2026年10月11日)。

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「Uncaught (in promise)の原因と直し方」

ブラウザと Node.js で、結果が違う

同じコードを、Chromium と Node.js 22 で動かしました。

コード Chromium Node.js 22
Promise.reject(new Error('x')) コンソールに Uncaught (in promise) Error: x、ページは動き続ける プロセスが終了(終了コード 1)
Promise.reject('NG')(Error ではない値) Uncaught (in promise) UnhandledPromiseRejection: ... The promise rejected with the reason "NG". で終了

ブラウザでは赤いエラーが出るだけで画面は動き続けますが、Node.js では、受け取られなかった失敗でプロセスごと止まりました。 サーバーやバッチの処理では、1件の失敗で全体が止まります。

原因1:await を付けずに呼んだ(try/catch で捕まらない)

async function load() { throw new Error('読み込み失敗'); }

try {
  load();                        // ← await が無い
} catch (e) {
  console.log('caught', e.message);   // ここには来ない
}

await を付けずに呼ぶと、エラーは「あとで失敗する Promise」として返るだけで、その場の try/catch では捕まりませんでした(Node.js は終了コード 1 で終了)。

try {
  await load();                  // await を付ける
} catch (e) {
  console.log('caught', e.message);   // caught 読み込み失敗
}

原因2:forEach の中の async

try {
  [1, 2].forEach(async (n) => { await load(); });
} catch (e) {
  console.log('caught');             // ここには来ない
}

forEach は、中の async の処理の終わりを待たず、失敗も受け取りません。 確認環境でも、Node.js は終了コード 1 で終了しました。

書き方 結果
forEach(async ...) 捕まらない
for (const n of list) { await load(); } 捕まった(1件ずつ順番に)
await Promise.all(list.map(n => load())) 捕まる(同時に実行)

原因3:then だけで catch が無い

load().then(v => console.log(v));                       // 失敗を受け取る場所が無い
load().then(v => console.log(v)).catch(e => console.log('caught', e.message));   // 受け取れた

catch は、then のつながりの最後に1つ付けます。

catch を「あとから」付けたとき

const p = load();
setTimeout(() => p.catch(e => console.log('caught late')), 10);
環境 結果(確認環境)
Chromium いったん Uncaught (in promise) Error: late が出て、catch が付いたあとに取り消された(DevTools の記録では Handler added to rejected promise)
Node.js 22 catch が付く前に、プロセスが終了(終了コード 1)

Node.js では、失敗した時点で受け取る処理が付いていないと、その時点で終了しました(Node.js の公式ドキュメントでも、イベントループの1周の間に受け取る処理が付かないと unhandledRejection になるとされています)。Promise は、作ったらすぐに await か catch を付けます。

原因4:fetch の 404・500(エラーにならない)

fetch('/api/notfound')
  .then(r => { console.log('status', r.status, 'ok', r.ok); return r.json(); })
  .then(d => console.log(d));
status 404 ok false
Uncaught (in promise) SyntaxError: Unexpected token '<', "<!DOCTYPE "... is not valid JSON

fetch は、404 でも失敗(reject)にならず、続く r.json() で HTML を JSON として読もうとして失敗しました。 MDN でも、fetch はネットワークのエラーのときだけ失敗し、404・500 では失敗しないので、response.ok を確かめるよう書かれています。

const r = await fetch('/api/notfound');
if (!r.ok) throw new Error('HTTP ' + r.status);    // 404 なら自分で失敗にする
const data = await r.json();

この形のエラーは、関連記事の「Unexpected token '<' in JSONの原因と直し方|fetch」と「Failed to fetchの原因と直し方|fetchエラー」で詳しく扱っています。

受け取られなかった失敗を、まとめて検知する

環境 書き方 結果(確認環境)
ブラウザ window.addEventListener('unhandledrejection', e => { ...; e.preventDefault(); }) 受け取れ、preventDefault() でコンソールのエラー表示も止まった
Node.js process.on('unhandledRejection', (reason) => { ... }) 受け取れ、プロセスは終了しなかった
Node.js node --unhandled-rejections=warn app.js 警告(UnhandledPromiseRejectionWarning)を出して、動き続けた

これらは「最後の網」です。 ログを送る・エラーの画面を出すために使い、個々の処理には await と try/catch を書きます。Node.js で unhandledRejection を受け取って処理を続けると、失敗した処理の途中の状態のまま動き続けることになるので、ログを出したあとに終了させる作りも検討します。

確認の手順(チェックリスト)

順番 確認すること 方法
1 元のエラー in promise の後ろ(TypeError・SyntaxError など)
2 async の関数を await しているか 呼び出し元に await があるか
3 forEach の中の async for...of か Promise.all に
4 then のつながり 最後に .catch があるか
5 fetch r.ok を確かめているか
6 Node.js 終了コード 1、process.on('unhandledRejection') でログ

よくある質問

Q. エラーを消すだけなら、空の catch を付ければよいですか。 A. .catch(() => {}) でエラーは表示されなくなりますが、失敗したことに誰も気づけなくなります。少なくともログに出し、画面なら「読み込みに失敗しました」などを表示します。

まとめ

  • Promise の失敗を、誰も受け取らなかったエラー。後ろに元のエラーが続く
  • ブラウザは表示だけ、Node.js 22 はプロセスが終了(終了コード 1)
  • await を付けずに呼ぶと、try/catch で捕まらない
  • forEach(async) は失敗を受け取らない。for...of か Promise.all
  • fetch は 404 でも失敗にならない。r.ok を確かめる
  • まとめて検知は unhandledrejection・process.on('unhandledRejection')

参考・出典

確認日はいずれも 2026年10月11日です。

  • MDN「Window: unhandledrejection event」:https://developer.mozilla.org/en-US/docs/Web/API/Window/unhandledrejection_event
  • MDN「Window: fetch() method」:https://developer.mozilla.org/en-US/docs/Web/API/Window/fetch
  • Node.js Documentation「Process」(Event: 'unhandledRejection'):https://nodejs.org/api/process.html#event-unhandledrejection

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「Uncaught (in promise)の原因と直し方」

株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。

WE ARE HIRING

RJCで一緒に開発しながら、
成長を楽しみませんか?

RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!

  • 127日年間休日
  • 12時間平均残業時間
  • 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!

ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。

ABOUT RJC RJCがどんな会社か知る 考え方、研修、働き方、福利厚生、社員の前職まで。RJCのことが丸わかり! RJC丸わかりページへ JOB DESCRIPTION 仕事内容・待遇を見てみる 仕事内容、給与・待遇、選考の流れ。経験者も未経験も!応募前に知りたいこと、まとめました! 募集要項を見る ENTRY エントリーする エントリーは1〜2分・履歴書不要です。まずは話を聞いてみたい、という方でも歓迎です! エントリーフォームへ

RJCで一緒に開発しながら、 成長を楽しみませんか?