closed は fixed ではなかった ── 設定が静かに壊れる4つのバグと、その全部が自動で閉じられていた話

closed は fixed ではなかった ─ 設定が静かに壊れる4つのバグと、その全部が自動で閉じられていた話(モトトリラボ) AIツール活用術

設定ファイルの1行を書き換えるつもりで、同じファイルの中の別の6行を壊していました。壊れていたのは約72分。その間、エラーは一度も出ていません。動いているように見えて、肝心の設定が読まれていなかった。

普通のバグはエラーが出ます。赤い文字が出て止まるので、そこから直せばいい。最近わたしが踏んでいるものは、エラーが出ません。テストは通り、目視でも異常がなく、grep(=要するに、ファイルの中から文字列を探すコマンド)でも見つからない。失敗が失敗として現れないので、気づいたときには影響が確定しています。

これは Windows で Claude Code(=要するに、AIにコードを書かせるコマンドラインの道具。使い方の全体像はClaude CodeとObsidianで個人用ナレッジベースを作った話に書きました)を数か月使って踏んだ記録です。ただ、いちばん言いたいのは道具の話ではなく、「直った」と書いてある場所を信じすぎないという話です。読み終えると、設定ファイルの壊れを機械で見つける手順が3つと、「対応済み」を確認する前に信じない癖が残るはずです。開発をしない人にも、たぶん通じます。


72分の中身

壊したのは、AIのセッションを別の作業場所から隔離する設定でした。JSON(=要するに、決まった書式のテキスト)で書かれていて、日本語のフォルダ名を含むパスが6行ありました。

わたしは PowerShell(Windows に入っているシェル)で1行を書き換えました。ここに落とし穴がありました。ファイルは BOM なしの UTF-8 で、Windows PowerShell 5.1 の Get-Content は文字コードを指定しないと、それを日本語 Windows 既定の文字コードとして読みます。 日本語のフォルダ名は読んだ時点で化け、そのまま書き戻されたので、6行は実在しないフォルダを指す文字列になりました。隔離はその瞬間から効いていません。

気づいたのは、設定の中の許可・禁止のリストを、正常だったときのリストと30分おきに突き合わせる監視スクリプトでした。16時31分と17時01分に警告が出て、17時13分にバックアップから復旧しました。同じ時間帯にわたしは grep で確認して「問題なし」と判断していました。理由は後で分かります。


同じ系統の報告が、公式リポジトリにある

Anthropic の公式リポジトリの Issue(=要するに、開発元への不具合報告の1件1件)に、同じ系統の報告が続いていました。番号は覚えなくて大丈夫です。あとで効くのは最初の1つだけです。

  • #25601 — 権限設定のバックスラッシュが JSON の特殊記号として解釈され、設定が黙って壊れる
  • #33650 — 引用符を含む検索パターンの書き方ひとつで設定ファイルが壊れる。Windows 特有と明記
  • #48317 — AI が文字列の中の特殊記号の扱いを繰り返し間違える
  • #59225 — Windows では AI に「シェルは PowerShell」と伝えられているのに、フック(=要するに、決まったタイミングで自動実行される小さなスクリプト)は bash で走る

ここまでは「まだ直っていない既知の問題」の確認のつもりでした。


4件とも closed だった。でも fixed ではなかった

Issue の状態を見て、手が止まりました。4件とも closed(=閉じられた状態)で、4件とも修正(fixed)への言及がありません。

閉じたのは人ではなく、一定期間動きがない Issue を自動で閉じる bot(=要するに、人の代わりに決まった作業をするプログラム)でした。3件は「not planned」の区分ですが、これは「対応しないと決めた」ではなく、完了以外の理由で閉じたことを表す機械的なラベルで、bot が閉じれば自動的にこうなります。人が判断した痕跡はありません。

残る #25601 は「重複」として閉じられていました。重複先の #24515 を開くと、投稿者は原因をコードの場所まで特定し、自分で検証したという修正パッチを載せていました(検証したのは投稿者で、わたしが試したわけではありません)。bot の「既存3件と重複」という提示に対して「症状が同じなだけで根本原因は別」と反論もしています。それでもメンテナ(=要するに、開発元の担当者)のコメントは付かず、この Issue も bot に閉じられました。bot が候補に挙げた Issue と、実際に重複先として紐づけた Issue も、別の番号でした。

事実だけ並べるとこうです。#25601 は、修正の入っていない Issue に重複として吸収され、その先も bot に閉じられた。

公式の changelog(=要するに、バージョンごとの変更点一覧)も全バージョン分(約390本)を backslashescapeBOMhooksPowerShell の5語で検索しました。関係しそうな項目は1つだけで、それは Improved(エラーメッセージの改善)であって Fixed ではありません。言葉で探した結果なので見落としの可能性は残ります。公開前の2026年9月12日にも5件の Issue と最新版までの changelog を再確認しました。変わっていませんでした。


書いている最中に、自分の環境でもう1件

ここまで書いた日の夜、アプリのログに「設定ファイルの読み込みに失敗(構文エラー)」が3週間分で838行残っているのを見つけました。原因は UTF-8 BOM。ファイルの先頭に付く、目に見えない3バイトです。JSON の仕様(RFC 8259)は「BOM を付けてはならない」と定める一方で「読み手は無視してもよい」とも書いているので、通る読み手と落ちる読み手の両方が正しい状態が生まれます。

なぜ付いたのか。このプロジェクトでは .ps1(PowerShell スクリプト)に BOM を付けるのが必須なんです。Windows PowerShell 5.1 は BOM がないと日本語を壊すからです(PowerShell 7 にこの制約はありません)。

.ps1 は BOM がないと壊れ、.json は BOM があると壊れる。要件が正反対でした。 薬の飲み合わせと同じで、片方だけ覚えていれば、いつか逆をやります。わたしのメモには「.ps1 は BOM 必須」だけがあり、対になる情報がありませんでした。


一番こたえたのは、確認に使っていた道具のほうでした

「壊れているのでは」と疑ったとき、わたしは PowerShell で読み込みを試しました。結果は OK。それで一度、安心しかけたんです。

理由はこうです。PowerShell の Get-Content はファイルを読む段階で BOM を文字コードの目印として消費するので、その先の JSON の解析器には BOM が届きません。だから壊れたファイルを「正常」と報告します。アプリが実際に使っているのと同じ厳密な読み手(Node.js の JSON.parse)で試したら、一発で失敗しました。

確認に使っていた道具そのものが、壊れを隠していたわけです。狂った体温計で「平熱」と出ていたようなものです。以前書いた体組成計の自動取得が、初回に来なかった話も「失敗が通知されない」話でしたが、あれは無人実行の側の話で、今回は確認する側の道具と、公式の課題管理そのものが同じ穴を持っていた、という違いがあります。72分の事故で grep が素通りしたのも同じ構造で、確認する側のシェルが化けた文字列を検索語として渡すので、化けたファイルとは一致せず「見つからない=問題なし」に見えていました。


で、自分はどうしているか

全部、実際にやっていることです。

1. .ps1 は UTF-8 BOM 付き、.json には付けない(Windows PowerShell 5.1 の環境の話です)。先頭3バイトを見れば分かります。PowerShell で [IO.File]::ReadAllBytes("ファイル名")[0..2] を実行して 239 187 191 なら BOM 付きです。

2. 設定ファイルの検査は、実際に読む側と同じ読み手でやる。 読む側が Node.js 系なら node -e "JSON.parse(require('fs').readFileSync('ファイル名','utf8'))" の1行で、BOM 付きならその場で落ちます。Python なら json.load が同じ役目です。大事なのは Node.js ではなく「そのアプリと同じ厳密さで読む」ことです。

3. 文字化けの確認を目視と grep に頼らない。 正常だったときのリストを別ファイルに置き、機械的に突き合わせる。72分の事故を拾ったのはこれだけでした。git diff で差分を見るのも同じ発想です。

4. AI に渡す正規表現では \d を避けて [0-9] と書く。 自分の環境では、AI の道具を経由すると文字列の中のバックスラッシュが潰れることがありました(#25601 と同じ系統の現象です)。全角数字を扱う場面では意味が変わるので、その場合は別途考えます。

5. バージョン管理を入れて、差分で見る。 最近入れたばかりです。それまで1000ファイル・20万行を履歴なしで AI に毎日書き換えさせていました。入れた日にアプリが2回落ちましたが(原因は自動アップデートで無関係でした)、失ったのは自動追記のログ1行だけだと差分ですぐ確かめられました。


先に書かれている記事があります

Qiita と Zenn に、許可ルール152件のうち完全一致で書いた92件が10万回以上の実行で一度も効いていなかった、という実測記事があります(Tsutomu_eng 氏)。保存時に括弧が特殊記号に書き換えられて文字列比較が外れる、という #25601 と地続きの話です。あちらは「ルールが腐っていく」問題として、こちらは「Issue が未修正のまま閉じられている」という読み方の問題として書いています。


closed を「直った」と読み替えない

Issue が閉じられていることは、直った証拠ではありません。自動で閉じられた Issue は、少なくとも閉じた時点で人の判断が入っていないことは確かです。パッチまで書いてあっても閉じられます。

これは Claude Code に限った話ではないと思います(複数のAIサービスに課金する判断を言語化した記事でも、結局は「自分で確かめた事実」しか判断材料にならないという同じ結論に着きました)。あらゆる Issue トラッカー(=要するに、不具合や要望を1件ずつ管理する仕組み)の読み方の問題で、仕事で「対応済み」と返ってきた依頼を確認せずに流すのと同じ形をしています。「closed だから対応済みだろう」と流したくなったときが、たぶん一番危ないところです。

念のため、ここに挙げた内容は「調べた範囲では」の話です。Issue の状態は変わりますし、わたしが辿れなかった先で修正が入っている可能性もあります。判断する前に、ご自身で現在の状態を確認してください。それがまさに、この記事で言いたかったことです。

Comments

タイトルとURLをコピーしました