障害の調査でログを開いたものの、手がかりがほとんど残っていないことに気づいた開発者

AIにエラーハンドリング方針を相談する|握りつぶさない設計

「ユーザーから、保存できていないと連絡がありまして」。そう言われてログを開いたら、残っていたのは「エラーが発生しました」の一行だけだった。——この静けさ、経験があるかもしれません。

処理は落ちていません。監視も鳴っていません。画面には「完了しました」と出ていた。それなのに、データだけが入っていない。どこで失敗したのかを知る手がかりが、もうどこにも残っていない。

これは、確認が甘かったから起きるのではありません。エラー処理は「うまくいかなかったとき」にしか動かないので、普段の動作確認では一度も通らないという性質を持っているだけです。AIに書いてもらったコードなら、なおさらです。この記事では、そこをAIとどう分担するかを整理します。

結論:AIにエラーハンドリングを任せるときの要点は3つです。①コードを頼む前に、エラーの行き先を3つに仕分けて渡す——利用者に伝える/後で調べられるように残す/一時的な失敗なら立て直す②「エラー処理を書いて」ではなく「失敗したのに、そのことが誰にも残らない箇所を挙げて」と頼む。AIは、書くことより抜けを名指しすることのほうが得意です。③失敗する経路を1つだけ、実際に起こしてみる——外部の接続を切る、必須項目を空で送る、そのどちらか1つで十分です。

AIが苦手なのは、そのエラーが起きたときに、あなたの現場では誰が何をするのかを知ることです。そこだけこちらが決めて渡せば、あとはかなり頼れます。

全部を今日やる必要はありません。まずは①の仕分けからで大丈夫です。

何が起きているのか——エラー処理は「頼まれていない仕事」になりやすい

受付で利用者に説明する場面、ノートに書き留める場面、倒れた積み木を積み直す場面を並べた図
捕まえたエラーには行き先が要る。誰かに伝えるのか、後のために残すのか、自動で立て直すのか

まず、なぜここだけ勝手が違うのかを共有させてください。理由は3つあります。

1つ目は、こちらが頼んだのが「正常系」だということ。「この処理を書いて」と頼めば、AIはうまくいく道筋を書きます。エラー処理は、そのついでに添えられる部分です。ついでに添えるなら、いちばん無難な形——とりあえず捕まえて、一行だけ記録して、そのまま先へ進む——になります。手を抜いたわけではなく、どう扱ってほしいかを一言も伝えていなかっただけです。

2つ目は、捕まえる場所が決まっていないこと。ここが実は本丸です。エラーを捕まえるという操作は、それ自体が「私がこの失敗の責任を引き受けます」という宣言に近い。ところが引き受けたのに何も決められない場所で捕まえると、記録を一行残して先へ進むしかなくなります。図でいえば、行き先を決めないまま受け取ってしまった状態です。呼び出した側は、失敗があったことすら知りません。AIはファイル単位・関数単位で書くので、「上の階層が何をするか」を知らないまま、目の前で捕まえます

3つ目は、消えた情報は後から戻せないこと。エラーには、いつ・どこで・何をしようとして失敗したのかという手がかりが付いています。捕まえて自前のメッセージに詰め替えると、この手がかりは落ちます。落ちた瞬間には誰も困りません。困るのは数週間後、障害の調査を始めたときです。冒頭の「エラーが発生しました」の一行は、こうしてできあがります。

この3つが重なると、「レビューも通り、動作確認も通り、障害のときだけ何も分からない」という状態になります。逆に言えば、エラーの行き先を先に決めて渡すだけで、かなりの部分は入口で防げるということでもあります。

具体例——AIのエラー処理は、こう抜ける

現場で見かけやすいのは、次のような形です。一つでも心当たりがあれば、この記事はそのまま使えます。

どれも、注意力の問題ではありません。これらは「動いてしまう」ことが特徴なので、動かして確かめるという普段のやり方では見つからない、というだけです。見つけにくいものを相手にしている——そう捉えるほうが、実態に近いと思います。

影響——困るのは、いちばん急いでいるとき

エラー処理の抜けが少し特別なのは、平時にはまったく害がないところです。顔を出すのは、決まって障害の最中です。

ただ、ここは強調しておきたいのですが、この種の抜けは、書く前なら本当に安く塞げます。あとから探すのは大変でも、先に「このエラーは誰に何を伝えるのか」を問うのは1分です。いま実装の手前でこの記事を読んでいるなら、それはいちばん安いタイミングにいるということです。

明日からやること(3ステップ)

大がかりな設計変更は要りません。この順番で、今日から小さく始められます。

1. AIに頼む前に、エラーの行き先を3つに仕分ける

いきなり「エラー処理も入れて」と頼まないほうが、返ってくるものの質が変わります。先に、想定する失敗を次の3つに分けます。図の3つの列がそのまま対応します。

①伝える:利用者が自分で直せる失敗(入力の不備、権限がない、期限切れ)。→ 何が起きたかより、次に何をすればいいかを書く。
②残す:想定していなかった失敗(プログラムの誤り、前提が崩れた)。→ 処理は止めて、原因ごと記録して、上へ渡す
③立て直す:一時的な失敗(通信が切れた、混み合っている、相手が一時的に落ちている)。→ 少し待って数回だけ再試行し、それでもだめなら②へ落とす

そのうえで、もう1行だけ決めます。捕まえるのは、そのエラーについて何かを決められる場所だけ。決められないなら、捕まえずに上へ渡す。これは一行ですが、いちばん効きます。

例:

書いてみると分かるのですが、難しいのは③と②の線引きです。ここが埋まらないまま「エラー処理も入れて」と頼むと、AIはすべてを③のように——つまり、何となく続行するように——扱います。この仕分けは、AIが守るべき線をこちらから示す唯一の材料だと思ってください。この数行が、そのまま渡す素材になります。前提や制約の渡し方そのものはAIにコードを書かせる前に渡す前提と制約|伝え方の型と同じ考え方です。

2. 「握りつぶしている箇所」を名指しで挙げさせる

仕分けを渡したうえで、実装ではなく、抜けを先に聞きます。これはAIがかなり得意な仕事です。

そのまま使える頼み方の例:

以下のコードと前提について、修正案は出さなくて結構です。失敗したのに、そのことが呼び出し元にも記録にも残らない箇所」を挙げてください。それぞれ、①どんな失敗が起きたときか ②その事実がどこで消えるか ③消えると、後の調査で何が分からなくなるか、の3点で書いてください。とくに次の5点を名指しで見てください。

1. 捕まえたあとに処理を続けている箇所(呼び出し元が成功だと受け取らないか)
2. 捕まえる範囲が広すぎる箇所(プログラムの誤りまで飲み込んでいないか)
3. 元の原因を捨てて、別のエラーに詰め替えている箇所
4. null・空・false で失敗を表している箇所(呼び出し元が正常と区別できるか)
5. 途中で失敗したときに、後始末(接続・ファイル・ロック・トランザクション)が漏れる箇所

あわせて、利用者に見せる文言と、記録に残す内容が同じになっている箇所も指摘してください。

前提(エラーの行き先):
(ここに1で書いた仕分け)
コード:
(ここに対象のコード)

ポイントは、「修正案は出さなくて結構です」と先に伝えることです。これを言わないと、AIは指摘のあとに親切な修正コードを並べてくれて、そちらに目が行きます。いま欲しいのは、自分では見えていない「消えている場所」です。設計の抜けを洗わせる問い方は設計レビューの見落としをAIに洗わせる|プロンプトの型にも型をまとめています。

返ってきた指摘は、そのまま信じずに1つずつ「これは実際に困るか」を確かめてください。AIは、社内向けの小さなバッチにまで、利用者向けの丁寧なエラー表示を求めてくることがあります。全部に対応する必要はありません。 困るものだけ拾えば十分です。選り分け方はAIレビューの指摘を取捨選択する判断軸|直す・保留・落とすが使えます。

直し方まで進むなら、選択肢はそう多くありません。何も決められない場所では捕まえない(いちばん安い)、捕まえるなら元の原因を連れて上げる(前述の from e%wcause)、利用者向けの文言と記録用の詳細を分ける。3つ目をやるときは、問い合わせ番号のような短い識別子を1つ振って、画面と記録の両方に載せておくと、あとから一発でたどれます。「先ほどのエラー画面に出ていた番号を教えてください」で調査が始められるのは、かなり楽です。

3. 失敗する経路を、1つだけ実際に起こす

直したあと、直ったことをどう確かめるかが最後の壁です。ここも1つだけで構いません。エラー処理は、意図的に壊さないと一度も動かない部分です。

見るのは3つだけです。利用者の画面に何が出るか/記録に何が残るか/データが中途半端になっていないか。とくに2つ目は、実際に自分で読んでみてください。「この一行だけで、3週間後の自分は原因にたどり着けるか」。たどり着けないと感じたら、足りないのは情報です。落ちたあとの調査そのものを速くする話はスタックトレースをAIに読ませる|バグ調査を速くする渡し方にまとめてあります。

3つとも今日やる必要はありません。ステップ1の仕分けを書くだけでも、AIから返ってくるコードは変わります。

エラーハンドリングのチェックリスト

全部に○が要るわけではありません。気になった行だけで十分です。

① AIに頼む前に

② 返ってきたコードで

③ 出す前に

この記事のまとめ

AIはエラー処理のコードを、驚くほど速く、それらしく書きます。得意なのは書くことと、抜けを名指しすること。苦手なのは、そのエラーが起きたときに、あなたの現場で誰が何をするのかを知ることです。それは、渡していない情報だからです。

やることは3つだけです。①エラーの行き先を「伝える・残す・立て直す」に仕分けて渡す/②「修正案は出さなくていいので、失敗が誰にも残らない箇所を挙げて」と頼む/③失敗する経路を1つだけ実際に起こす。この3つがあると、エラー処理は「祈りながらリリースする作業」から、「決めて確かめる作業」に近づきます。

エラー処理の見直しを終えて、安心した表情で顔を上げている開発者

エラー処理が後回しになりやすいのは、それが「起きてほしくないこと」のための仕事だからだと思います。起きないことを願いながら備えるのは、地味で、誰にも褒められにくい。でも、障害の夜にログを開いた誰かを助けるのは、その地味な備えだけです。今日ひとつ「これが失敗したら、誰に何が伝わるだろう」と問えたなら、それだけで、未来の自分の調査を何時間か短くしています。

よければ、こちらも

関連用語