- JavaScript
Uncaught (in promise)の原因と直し方
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期連続の黒字決算。