undefined のプロパティを読もうとしたときに出ます。
x の部分には、読もうとしたプロパティ名が入ります。
const user = undefined;
console.log(user.name);TypeError: Cannot read properties of undefined (reading 'name')
at showName (file:///app/example.mjs:7:15)
at file:///app/example.mjs:10:13
at ModuleJob.run (node:internal/modules/esm/module_job:343:25)
at async onImport.tracePromise.__proto__ (node:internal/modules/esm/loader:681:26)user.name が undefined なのではありません。user そのものが undefined です。
ここを取り違えると、直す場所を間違えます。
まずスタックトレースを見る
const users = [{ id: 1, name: 'あかり' }];
const user = users.find(u => u.id === 2);
console.log(user.name);見るのは上から2行目、つまり at で始まる最初の行です。
example.mjs の7行15文字目で起きた、と書いてあります。
| 行 | 見るか | 何が書いてあるか |
|---|---|---|
| 1行目 | 見る | どのプロパティを読もうとしたか(reading 'name') |
| 2行目 | いちばん見る | 自分のコードのどこで起きたか |
| 3行目以降 | 見る | そこを呼んだのは誰か(呼び出しの道すじ) |
node:internal/ を含む行 |
無視してよい | 処理系の内部。原因はここにない |
node_modules/ や node:internal/ しか出ていないときは、
その1つ下の自分のコードの行まで下がって探します。
原因1: 探したものが見つからなかった(いちばん多い)
find() は見つからないと undefined を返します。例外は投げません。
id: 2 の人はいないので user は undefined です。
直しかた
見つからなかったときにどうするかを、その場で決めます。
const res = { data: {} };
console.log(res.data.user.name);「あるなら読む、無いなら undefined でよい」ならオプショナルチェーンが短く書けます。
function makeUser(name) {
const user = { name };
}
const user = makeUser('あかり');
console.log(user.name);?. は左が null か undefined なら、そこで止まって undefined を返します。
何でも ?. を付ければよいわけではありません。
「無いことが正常」な場所にだけ使ってください。本来あるはずのものが無いなら、それは不具合です。
原因2: 途中の階層が無い
深いところを一気に辿ると、どこで切れたか分からなくなります。
async function fetchUser() {
return { profile: { name: 'あかり' } };
}
const user = fetchUser();
console.log(user.profile.name);res.data はあります。無いのは res.data.user です。
エラー文の reading 'name' は読もうとしたものなので、
その1つ手前が undefined だと分かります。
直しかた
const el = null;
console.log(el.value);どこで切れたかを調べたいときは、手前から順に出します。
const user = { name: 'あかり' };
console.log(user.getName());原因3: 関数が何も返していない
return を書き忘れると、その関数は undefined を返します。エラーにはなりません。
直しかた
アロー関数で {} を書いたときも同じです。n => { n * 2 } は undefined を返します。
原因4: 待つ前に触った
await を書き忘れると、まだ結果ではなく Promise が入っています。
Promise に name は無いので undefined になり、その先で落ちます。
user は Promise です。user.profile が undefined になり、その .name で落ちます。
直しかた
このページの実行環境では、コードの一番外側でも await が書けます。
似ているエラーとの違い
null のとき
null だと文言が変わります。別の原因なので読み分けてください。
null は「無いことが分かっている」印です。ブラウザで
document.querySelector() が見つけられなかったときは null が返ります。
| 文言 | 中身 | 典型的な原因 |
|---|---|---|
... of undefined |
まだ入っていない / 返ってこなかった | find() が空振り、return 忘れ、await 忘れ |
... of null |
無いと分かっている | querySelector() が見つけられなかった |
関数ではないとき
プロパティは読めたが、それが関数ではなかった場合は別のエラーです。
こちらは TypeError: x is not a function にまとめてあります。
処理系によって文言が違う
同じ原因でも、書いてある文が違います。検索するときは自分の環境の文言で調べてください。
| 処理系 | 文言 |
|---|---|
| Node / Chrome(V8) | Cannot read properties of undefined (reading 'name') |
| Chrome(古い版) | Cannot read property 'name' of undefined |
| Firefox(SpiderMonkey) | user is undefined |
| Safari(JavaScriptCore) | undefined is not an object (evaluating 'user.name') |
このページの実行結果は Node 22.22.3 のものです。
起きにくくするには
- 見つからないことがある関数を覚える。
find()/at()/pop()/Map.get()/querySelector()は、空振りするとundefinedかnullを返します - 一気に辿らない。
a.b.c.dと書く前に、a.bが何かを確かめる ?.を保険として撒かない。 無いことが正常な場所にだけ使う。 そうしないと不具合が静かに先へ進みます
配列から目的の要素を取り出すときの find() と filter() の違いは
filter() にまとめてあります。