セキュリティの話をしてきましたが、実は AI で作ったアプリでいちばん多い不具合は脆弱性ではありません。
エラーが出ないまま、結果だけが間違っている。 これです。
そしてこの種のバグが厄介なのは、発見される機会がほとんど無いことです。画面は正常。エラーも出ない。ログにも残らない。数字が少し違うだけ。だから何ヶ月も、場合によっては永久に気づかれません。
1. なぜAIはこの種のバグを作るのか
AI は「うまくいく道筋」を書くのが非常に得意です。
「ユーザーの注文一覧を表示して」と頼めば、注文があるユーザーが、正常なデータで、1人だけアクセスしている状況で、完璧に動くコードを書きます。
書かないのは、こういう場合です。
- 注文が1件も無いとき
- 日付がちょうど境界にあるとき(月末の23:59:59)
- 同時に2人が同じデータを操作したとき
- 外部サービスが遅い/落ちているとき
- 数字がマイナスや極端に大きいとき
- 文字列に絵文字や特殊文字が入っているとき
これらは「異常系」と呼ばれます。そして——本番で実際に起きるのは、まさにこれらです。
理由は単純で、指示に含まれていないからです。AI が不注意なのではなく、あなたが「注文が0件のときは『まだ注文がありません』と表示して」と言わなかった。言うわけがありません。そんなことを考えるのは、一度それで痛い目に遭った人だけです。
2. 頻出する5つのパターン
実際によく見る形を、具体的に挙げます。どれも画面上は正常に見えます。
パターン1: 例外の握りつぶし
いちばん多く、いちばん危険です。
処理が失敗したときに、その失敗を捕まえておきながら何もしない。エラーは画面にも記録にも出ず、処理は何事もなかったように次へ進みます。
【起きること】
- 保存されていないのに「保存しました」と表示される
- メールが送られていないのに完了画面が出る
- 決済が失敗しているのに注文が確定する
AI がこれを書く理由は、エラーで止まらないようにするためです。「エラーが出ます」と伝えると、AI は「エラーが出ないように」してくれる。それが「エラーを無視する」形になることがあります。
確認方法: わざと失敗させてみてください。ネットワークを切る、必須項目を空にする、極端に長い文字を入れる。それでも「成功しました」と出たら、握りつぶしています。
パターン2: 日付の境界
集計やフィルタで、境界の1日(あるいは1秒)がずれる。
【起きること】
- 月次集計に月末の1日が入らない/翌月の1日が混ざる
- 「今日の注文」に、深夜0時前後の注文が入らない
- タイムゾーンがずれて、日本時間の朝が前日扱いになる
日本時間とUTC(世界標準時)の9時間差は、AI が特に間違えやすい場所です。手元で試すと正しく見えるのに、深夜帯だけずれる——という形で出ます。
確認方法: 月末と月初にデータを1件ずつ作り、両方が正しい月に集計されるか見てください。深夜0時前後のデータも試すと、なお確実です。
パターン3: 並び順が不定のページ送り
一覧を「20件ずつ」表示している場合、並び順を明示していないと、2ページ目で一部が抜けたり重複したりします。
データベースは、並び順を指定しなければ「どの順で返してもよい」と考えます。1ページ目と2ページ目で違う順序が返ることが、実際に起こり得ます。PostgreSQL の公式ドキュメントにも、ORDER BY を指定しない LIMIT は行の順序が予測不能である旨が明記されています。
【起きること】
- ページ送りすると、一部の項目が表示されない
- 同じ項目が2ページに出る
- データが少ないうちは正常で、増えると突然おかしくなる
これはデータが増えてから顕在化するのが特に厄介です。
確認方法: 30件ほどデータを入れて、1ページ目と2ページ目を見比べてください。合計が30件になり、重複が無いことを確認します。
パターン4: 丸め誤差
金額や割合の計算で、小数点以下の扱いがずれる。
【起きること】
- 明細の合計と、表示されている総額が1円違う
- 消費税の計算が、税込→税抜→税込 で元に戻らない
- 割引を適用すると、合計がマイナスになる
1円の違いでも、会計上は問題になります。金額は小数で扱わず整数(円単位)で持つのが定石ですが、AI は指示しなければ小数で書くことがあります。
確認方法: 端数が出る金額(1円、333円、消費税の対象など)で試し、明細を自分で足した数字と画面の合計を突き合わせてください。
パターン5: 部分的な失敗の無視
複数の処理をまとめて行うときに、途中で失敗しても続行してしまう。
【起きること】
- 注文は作られたが、在庫が減っていない
- ユーザーは削除されたが、そのユーザーのデータが残っている
- 決済は完了したが、注文レコードが作られていない
「まとめて成功するか、まとめて失敗するか」を保証する仕組み(トランザクション)が必要ですが、これも明示しないと入りません。
確認方法: これは目視が難しい部類です。次章の指示文でAIに調べさせるのが現実的です。
3. 見つけ方 — コードが読めなくてもできること
原則は1つです。
正解を別の方法で計算して、突き合わせる
画面に出ている数字が正しいかどうかは、画面を見ても分かりません。別ルートで検算する必要があります。
方法1: 少ないデータで手計算
これが最も確実です。
データを3〜5件だけ入れた状態で、画面の集計と手計算を突き合わせます。件数が少なければ、暗算でも検算できます。
多くの人は「本物っぽいデータをたくさん入れて」試そうとしますが、それだと検算できません。わざと少なくするのがコツです。
方法2: 境界を狙う
正常な真ん中の値ではなく、端を試します。
- データが 0件 のとき
- データが 1件だけ のとき
- 月末・月初、深夜0時前後
- 金額 0円、マイナス
- 名前が 1文字、絵文字だけ、非常に長い
AI は真ん中の値では間違えません。端で間違えます。
方法3: わざと失敗させる
- 途中でブラウザを閉じる
- 通信を切って送信する
- 同じボタンを素早く2回押す
- 別のタブで同じ操作を同時にする
「同じボタンを2回押す」は特に有効で、二重登録や二重送信を一発で暴きます。
4. 対策 — 「壊れてはいけない条件」を先に書く
ここが本題です。
多くの人は、AI に「テストを書いて」と頼みます。それ自体は良いのですが、AI は自分が書いた実装に合わせてテストを書きます。実装が間違っていれば、テストも同じ間違いを前提にします。テストは通り、バグは残ります。
有効なのは、順序を逆にすることです。
あなたが書くもの
コードは書けなくても、「これは必ず成り立つ」という条件は日本語で書けます。むしろ、それを書けるのはあなただけです。アプリが何をすべきかを知っているのはあなたなので。
例:
- 注文の合計金額は、必ず明細の金額の合計と一致する
- 同じ検索を2回実行したら、必ず同じ順序で同じ件数が返る
- ページ送りで全ページを回ると、重複も欠落もなく全件が出る
- 残高は絶対にマイナスにならない
- ユーザーを削除したら、そのユーザーのデータは1件も残らない
- 月次集計は、月初0時00分00秒から月末23時59分59秒までを含む(日本時間)
- 決済が失敗したら、注文は作られない
- 保存に失敗したら、必ず画面にエラーが表示される
これを先に書いて、AI に「これをテストにして、実装が満たしているか確認して」と頼みます。
満たしていなければ、実装のほうを直します。この順序だと、AI は自分の実装を正当化できません。
5. AIに貼る指示
現状を調べる
このアプリのコード全体を読んで、次の観点で問題がある箇所を洗い出し、
表にして報告してください。修正はまだしないでください。
(1) 例外を捕まえて何もしていない箇所(握りつぶし)。ユーザーにも記録
にも失敗が伝わらない箇所
(2) 日付・時刻の境界の扱いが怪しい箇所。特にタイムゾーンの変換と、
月初/月末の含み方
(3) 一覧取得で並び順(ORDER BY)を指定していない箇所。特にページ送り
があるもの
(4) 金額や割合の計算で、小数を使っている箇所。丸めの方向が明示されて
いない箇所
(5) 複数の更新をまとめているのに、トランザクションになっていない箇所
(6) データが0件・1件のときの分岐が無い箇所
各項目について「どういう条件のときに、画面上どう間違って見えるか」を
日本語で説明してください。私はコードが読めません。
条件をテストにする
以下は、このアプリで必ず成り立つべき条件です。これらをテストとして
書き、実装が実際に満たしているか確認してください。満たしていない
ものがあれば、テストではなく実装のほうを修正してください。
- (ここに、あなたが書き出した条件を並べる)
テストは境界値(0件、1件、月末、深夜0時、金額0円やマイナス)を必ず
含めてください。テストが失敗した場合は、失敗した条件と、実装の
どこが原因かを日本語で説明してください。
6. 「直しました」を信じない
最後に、この領域で最も重要な習慣を1つ。
AI は「修正しました」と報告します。多くの場合、実際に修正されています。しかし確認せずに信じるのは、この種のバグでは特に危険です。エラーが出ないバグなので、直っていなくても何も起きないからです。
修正後は、見つけたときと同じ手順で確認してください。
- 少ないデータで手計算と突き合わせる
- 境界(月末、0件、1件)で試す
- わざと失敗させる
1回2〜3分です。この習慣があるかどうかが、公開後に静かに壊れているアプリと、そうでないアプリの差になります。
まとめ
- AI生成コードで最も多い不具合は脆弱性ではなく、エラーが出ないまま結果が間違っているバグ
- AIはハッピーパスを書くのが得意で、異常系は明示しない限り書かない。本番で起きるのは異常系のほう
- 頻出は5つ — 例外の握りつぶし、日付の境界、並び順が不定のページ送り、丸め誤差、部分的な失敗の無視
- 見つけ方は「別の方法で検算する」。データを少なくして手計算、境界を狙う、わざと失敗させる
- 対策は「壊れてはいけない条件」を先に日本語で書き、それをテストにしてもらうこと。コードが読めなくても条件は書ける
- 「AIが直したと言った」は確認にならない。同じ手順で再確認する
セキュリティの穴は「攻撃されなければ起きない」問題ですが、この種のバグは放っておいても必ず起きます。優先度としては、公開前の4項目を潰したあと、次にここへ来るのが現実的です。