開発環境に溜まった4つの不具合を一日で片付けた記録
開発環境に溜まった4つの不具合を一日で片付けた記録
今日は、種類も原因もまったく違う「動かない」を4つ、順番に片付ける一日になった。 ノートPCのスクロール、記事のプレビュー、Chrome拡張機能、開発環境のプロセスそのもの。 関連はなく、ただ順に潰していくしかなかった。
ThinkPadの横スクロールをめぐる残タスク
8月11日から追いかけていたThinkPadのトラックポイントの横スクロール不具合の計画書には、残タスクが4件残っていた。 次にやることとして書かれていたのは「再起動を1回はさみ、HScrollFun.exeが自動常駐するかwatchdog.logで確認する」という一文だった。
朝、その計画書を見て、まず確かめたいことがあった。 残っている実験は自分がやるべきものだったか。 数日前、モニタの電源が落ちて、電源ボタンを押し直す機会があった。 そのあとスクロールは普通に効いていた。 だとすれば、もう全部終わっているのではないか。
ログを確認させると、残タスク4件のうち3件はその場で確定できた。 見張りタスク(タスクスケジューラ)が06:08:00に発火し、HScrollFun.exe(PID 23412)がSessionId 1で起動していた。 watchdog.logには「STARTED」と記録されていた。 すでに動いていたことを示す「ALIVE」ではなく「STARTED」という記録だった。 これは、ログオン直後の時点ではまだ起動していなかった、ということになる。 前日2026-08-12の再起動でも同じ挙動だった。
つまり、Lenovo純正の自動起動経路は第1世代ドライバを削除したあとも現れておらず、見張りタスクが唯一の起動経路として機能し続けている。 恒久対策は効いている、と結論が出た。 残タスクをすべて完了とし、計画書のcarryoverをstatus: doneに更新させた。
自分が実験したのは電源ボタンを押した一度きりで、あとの確認作業はログを読むだけで済むものだった、と念を押された。 「それ以外はもう終わりってことですか」と聞くと、記事への追記が残っていた。 descriptionから直させ、devサーバーでlintを走らせ、実際の描画を確認させてから、学習ゲートをスキップしてコミットさせた。
記事プレビューがConnection refusedで止まる
新しく書いた記事をローカルで確認しようとしたら、ブラウザが「Connection refused」を繰り返した。
開こうとしていたのはPiのコーディングエージェントについての記事で、URLはhttp://localhost:3001/pi-coding-agent-local-llmだった。
「これ進んでますか?」「なんで止まるか教えてくれませんか? このFirewallProxyMaybeBlockedって。」と聞いた。 返ってきたエラーは「Connection refused — a firewall or proxy may be blocking it」で、リトライを10回繰り返してもつながらなかった。
調べさせると、原因はファイアウォールでもプロキシでもなかった。 ブラウザには以前開いたlocalhost:3001のタブが残っていたが、開発サーバー自体はすでに停止していた。 しかもこの作業のルール上、そこから新しく開発サーバーを起動することはできない。 その場でのプレビューはできない、という結論になった。
代わりに、Markdown構文とfrontmatterのスキーマ、公開パスの重複だけを静的に検証させた。 実際の見た目の確認は、次に開発サーバーが動いている状態のときに持ち越しになった。
Chrome拡張のダウンロードボタンが動かない
Twitter動画のダウンロード用に自作したChrome拡張で、投稿のダウンロードボタンを押したら「Error when communicating with the native messaging host」というエラーが出た。
ログの場所(%LOCALAPPDATA%\Temp\x-video-downloader.log)まで書いてあるエラー画面をスクリーンショットに撮って渡し、原因を探らせた。
Python、yt-dlp、保存先ドライブ、レジストリといった環境自体は揃っていた。 batファイル経由で直接通信を試させると応答は正常に返ってきて、実URLでダウンロードさせると本当に保存先ドライブに保存された。 つまりネイティブホスト自体は健全で、Chromeからの接続だけが失敗していることになる。
ログを見ると、その日記録されていたのはテスト分の1行だけで、ボタンを押した瞬間(09:18頃)の記録がどこにもなかった。 Pythonが起動すらしていない、ということだ。 bat→PowerShell→pythonという3段構えの呼び出しを疑わせた。 PATHにpythonが見つからない場合は標準出力が空のまま終わってしまい、Chrome側からは通信失敗としか見えない、という仮説にたどり着いた。
拡張機能のボタン配置(返信、リツイート、いいね、ダウンロード、ブックマーク、共有)を確認させたあと、実際にダウンロードボタンを押させると、同じエラーが即座に再現した。
Chromeが拡張を起動する環境をそのままダンプさせ、決定的な一行(where pythonの結果)を確認させると、ChromeのPATHにPythonが入っていないことが確定した。
where powershellは通っていたので、Chrome自身は動いているのに、その先のPythonにだけたどり着けていなかった。
同じ理由でyt-dlpもPATH頼みで見つからなくなる作りだったので、あわせて修正させた。 修正後、Chromeと同じ痩せたPATHを再現して検証させると、一度はstderrに別のバグが出た。 batに書き足した日本語コメントがcp932として誤解釈され、コマンドの一部として実行されてしまっていた。 ASCIIだけの表記に直させると、その問題も消えた。
最後にChromeから実際にダウンロードボタンを押させて確認した。 Pythonが起動し、保存先ドライブに35MBのファイルが届いた。 原因はChromeのPATHにPythonが入っていなかったこと、それだけだった。
走りっぱなしのdevプロセスとMCPサーバー
複数のClaude Codeセッションを開いていると、devサーバーやMCPサーバーが二重三重に立つ。
/procsコマンドで一覧を出させると、ちょうどそのタイミングで本番ビルド(nuxt generate)が14:00:56から走っていた。
メモリは4.6GBまで膨らんでおり、10分ほどかかる処理だった。
このビルドは過去に空きメモリ不足で0xC0000142として落ちたことがある。
今のうちにMCPを掃除しておくのは理にかなっている、という判断だった。
22個を止めさせた。 結果は24個から2個(このセッション分のみ)に減り、2,521MB解放された。 ビルドは生きたまま6.5GBまで膨らんでいった。
数字だけ見ると引っかかる部分があった。 空きメモリは7.7GBから6.0GBへ「減って」いた。 掃除したのに減っている、というのは一見矛盾に見える。 実際には、ビルドが4.6GBから6.5GBへ1.9GB膨らんだ分がそのまま反映されているだけで、掃除していなければ3.5GB程度まで落ちていた計算になる。 過去にクラッシュしたときの空きは3.9GBだったから、掃除しなければ危ない水準に入っていた。
「どうやればいいんですか、コマンドは。これはexitであればいいんですか?」と尋ねた。
/exitで合っている、という答えとあわせて、それでMCPが本当に落ちるのかを実測させた。
途中、「親不在のプロセスは9個ともClaude本体が終了済み」という説明が一度出たが、これは訂正された。
ParentProcessIdが指していたのはClaude本体ではなく、間にはさまるcmd.exeやnpxのシムだった。
シムはexec後に抜けるのが普通なので、親が不在なだけでは孤児プロセスの証拠にならない。
正常終了させて数えると、MCPプロセスの数は10のまま増減しなかった。
「Windowsだから残る」という以前の説明も、この実測で覆った。
そのあと、画面に出ていた「node×10」という数字が気になった。 「このセッションで10も立ち上がってるんですか。無駄なやつ立ってないんですか。」と聞き直した。 調べさせると、10個のうちこのセッションの分は4個だけだった。 現在のセッションはPID 34312で、残る6個の内訳を一つずつ洗い出させた。 仕分けはそこで一区切りになった。