マガジン

AI生成コードで「Cannot read properties of undefined」が出たら

遊びをつくる

執筆にClaudeを使用しています。

既存の木製ビー玉コースを保ちながら、一つの青い橋を慎重に足す手元
記事のテーマをもとに制作したAI生成イラスト。

AIにゲームのコードを生成してもらったとき、ブラウザのコンソールに Cannot read properties of undefined (reading 'xxx') と表示されて動かない、という経験は多くの人がします。このエラーは「存在しないはずのものを読もうとした」というJavaScriptの悲鳴で、原因の型はほぼ決まっています。 このエラーがAI生成コードで頻出する理由があります。AIは「動作する典型的なコード」を生成しますが、初期化のタイミングや非同期処理の順序、DOMの読み込み完了といった「実行順序」については、テンプレートどおりに書くだけで実際の動作を確認していません。そのため「変数が存在していない瞬間にアクセスする」コードが生まれやすいのです。 この記事では、エラーメッセージをどう読んで、どこを直すかを具体的に示します。AIに修正を依頼するときの伝え方も合わせて説明します。

この記事の目次
  1. エラーメッセージを3箇所で読む
  2. AIコードで多い原因パターン4つ
  3. AIへの修正依頼の書き方
  4. 自分でできる5分の予防策
  5. 次の行動

エラーメッセージを3箇所で読む

コンソールに表示されるエラーには3つの情報が含まれています。まずエラー本文の reading 'xxx' の部分——ここがアクセスしようとしたプロパティ名です。次に undefined という語——これはプロパティを持つはずの「親オブジェクト」がundefinedだったことを示します。そして行番号——「スタックトレース」の一番上に書かれているファイル名と行番号が実際にエラーが起きた場所です。

たとえば Cannot read properties of undefined (reading 'x') なら、「undefined.x を読もうとした」という意味です。undefined になっているのは .x の左側の変数です。行番号を見てその行の .x の前にある変数名を特定してください。それがこの調査の出発点になります。

Chromeでは行番号をクリックするとソースが開き、その行にジャンプします。コンソールを閉じずにここまで確認してから次の手順に進むと、修正の見当違いが減ります。

AIコードで多い原因パターン4つ

DOMの取得が空になっている

const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d'); // canvasがnullのとき落ちる

getElementById は要素が見つからないと null を返し、null もプロパティを読もうとすると同じエラーになります。AIは <canvas id="gameCanvas"> がHTMLにあると仮定してコードを書きますが、HTMLのid名がずれていたり、scriptタグがbodyより前にあってDOMがまだ構築されていない場合に発生します。確認すべきは、HTMLのidとJavaScriptの文字列が一字一句一致しているか、scriptタグが <body> の閉じタグ直前にあるか、またはDOMContentLoadedイベントの内側に処理を書いているかです。

配列・オブジェクトの初期化前アクセス

let enemies;
// ... 別の処理 ...
enemies[0].update(); // enemiesがundefinedのまま

AIはしばしば変数宣言と初期化を別の場所に書きます。let enemies; だけでは undefined のままで、enemies = [] という初期化を忘れているか、初期化より前のタイミングで使っている場合です。スクロールして変数の宣言行を探し、= [] や = {} が付いているか確認してください。

非同期処理の結果が来る前に使っている

let data;
fetch('data.json').then(r => r.json()).then(d => { data = d; });
draw(data.level); // fetchが終わる前に実行される

fetch などの非同期処理は、JavaScriptの他のコードが先に進んだあとで完了します。AIが生成するゲームコードではjsonデータを読んでステージ情報を構築するパターンがよく出てきますが、その結果を使う処理が .then() の外に書かれると、データが届く前に実行されてundefinedになります。修正の基本は、データを使うコードを .then() の内側に移すか、async/await で書き直して await を正しく置くことです。

ゲームループでオブジェクトが削除済み

enemies.forEach(e => {
  e.update();
  if (e.hp <= 0) enemies.splice(enemies.indexOf(e), 1);
});

ループ中に配列から要素を削除するとインデックスがずれ、すでに削除された要素にアクセスしようとするケースがあります。また e が削除されて undefined になった状態でプロパティを読もうとすることもあります。対策は削除を後回しにする方法(ループ後にfilterでまとめて除去する)か、アクセス前に存在チェックを入れることです。

AIへの修正依頼の書き方

このエラーをAIに直してもらうとき、「エラーが出ます」だけでは不十分です。次の情報をセットで渡すと精度が上がります。

  1. エラーメッセージの全文(Cannot read properties of undefined (reading 'xxx') の部分)
  2. エラーが起きた行番号とその前後10行程度のコード
  3. そのコードが「いつ実行されるか」の説明(ゲーム開始時か、ループ中か、ボタンクリック時かなど)

「エラーが出る行とその変数がどこで初期化されているかを確認し、undefinedになるケースを教えて、修正してください」と付け加えると、AIが原因の特定から始めてくれます。修正案が返ってきたら、「修正後にこの変数がundefinedになる状況はありますか」と追加で聞くと、別のパターンを見落としていないか確認できます。

自分でできる5分の予防策

AIにコード生成を依頼するとき、事前に次の3点を指示に含めると発生頻度が下がります。

  • 「DOMの取得はDOMContentLoadedの中で行う」
  • 「配列・オブジェクトは宣言と同時に初期化する(let enemies = [] の形で書く)」
  • 「非同期処理の結果を使うコードはasync/awaitで書く」

また生成されたコードを貼り付ける前に、document.getElementById の戻り値をすべてコンソールにconsole.logして null になっていないか確認する習慣をつけると、DOMがらみのエラーの多くを貼り付け前に潰せます。

エラーが出たあとの対処として、問題の変数の直前に console.log(変数名) を一行足してリロードするのが最速の確認方法です。コンソールに undefined が出れば、その行より前に初期化が必要だとわかります。

次の行動

エラーメッセージのスタックトレースから行番号を特定し、その行で . の左側にある変数を console.log で出力してみてください。undefined が表示されたら、この記事の4パターンのどれに当てはまるかを照合してください。修正したゲームは、ZIPまたはHTMLファイルとしてアソバースに投稿し、ブラウザで動作を確認する手順で最終確認ができます。