<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Codex</title><link>https://blog.ast.moe/tags/codex/</link><description>Recent posts from 五里霧中</description><generator>Hugo</generator><item><title>大量の無圧縮PNGを含むCodexの長期セッションでremote compactが失敗したので復旧した</title><link>https://blog.ast.moe/blog/2026-09-11-2/</link><pubDate>Fri, 11 Sep 2026 21:25:17 +0900</pubDate><guid>https://blog.ast.moe/blog/2026-09-11-2/</guid><description>&lt;p&gt;Codexで長期間続けていたスレッドが、突然使えなくなりました。&lt;/p&gt;
&lt;p&gt;表示されたエラーはこれです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Error running remote compact task: {&amp;#34;detail&amp;#34;:&amp;#34;Bad Request&amp;#34;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;一度失敗しただけなら再試行すればよさそうですが、このスレッドではcompactを試すたびに同じHTTP 400が返り、そのうち通常の応答まで失敗するようになりました。&lt;/p&gt;
&lt;p&gt;新しいスレッドへ移れば作業自体は続けられます。ただ、今回は長期間動かしていたGoalがあり、それまでの調査内容や判断もできるだけ維持したかったので、壊れたスレッドを調べて復旧することにしました。&lt;/p&gt;
&lt;h2 id="compactとは何か"&gt;compactとは何か&lt;/h2&gt;
&lt;p&gt;長い会話を続けると、過去のやり取りをすべてそのままモデルへ渡し続けることはできません。&lt;/p&gt;
&lt;p&gt;そこで、それまでの会話を圧縮した状態へ置き換え、続きを処理できるようにするのがcompactionです。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://developers.openai.com/api/reference/java/resources/responses/methods/compact"&gt;OpenAIのcompaction API&lt;/a&gt;では、会話をcompactすると、ユーザーメッセージと暗号化されたcompaction itemを含む出力が返ります。画像も入力として扱える仕様になっています。&lt;/p&gt;
&lt;p&gt;ただし、Codexが内部で使うremote compactionと公開APIが、まったく同じ制限で動いているとは限りません。&lt;/p&gt;
&lt;p&gt;今回のエラー本文は&lt;code&gt;Bad Request&lt;/code&gt;だけで、何が制限に当たったのかまでは分かりませんでした。&lt;/p&gt;
&lt;h2 id="まず履歴を壊さずに調べる"&gt;まず履歴を壊さずに調べる&lt;/h2&gt;
&lt;p&gt;復旧作業を始める前に、元のセッション履歴と関連するデータベースをコピーしました。&lt;/p&gt;
&lt;p&gt;元の履歴は約356 MBあり、5万行を超えていました。&lt;/p&gt;
&lt;p&gt;直接書き換えて失敗すると戻せないので、調査と再現試験はすべてコピー側で行います。コピー後はハッシュを比較し、元の履歴と同じ内容であることも確認しました。&lt;/p&gt;
&lt;p&gt;また、履歴を読むためのデータベースは読み取り専用で開き、バックアップAPIを使って複製しました。コピーしたデータベースには整合性検査もかけています。&lt;/p&gt;
&lt;p&gt;この時点では、元のセッション、Goal、作業ツリーには触れていません。&lt;/p&gt;
&lt;h2 id="有効なコンテキストの98が画像だった"&gt;有効なコンテキストの98%が画像だった&lt;/h2&gt;
&lt;p&gt;最後に成功したcompactと、それ以降の履歴から、現在の処理に使われるコンテキストを再構成しました。&lt;/p&gt;
&lt;p&gt;再構成できた項目は530件です。その中に、Base64のdata URLとして保存されたPNG画像が40枚ありました。&lt;/p&gt;
&lt;p&gt;集計すると、次のようになっていました。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;項目&lt;/th&gt;
&lt;th style="text-align: right"&gt;サイズ&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;PNGの実体&lt;/td&gt;
&lt;td style="text-align: right"&gt;約42.4 MB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Base64 data URL&lt;/td&gt;
&lt;td style="text-align: right"&gt;約56.6 MB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;再構成したJSONに占める割合&lt;/td&gt;
&lt;td style="text-align: right"&gt;約98.1%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;ほぼ画像です。&lt;/p&gt;
&lt;p&gt;40枚はすべて800×600ピクセルでした。PNGのチャンクCRCとzlib展開も確認しましたが、ファイルが壊れているわけではありません。&lt;/p&gt;
&lt;p&gt;問題は圧縮方法でした。&lt;/p&gt;
&lt;h2 id="自作側が無圧縮pngを出していた"&gt;自作側が無圧縮PNGを出していた&lt;/h2&gt;
&lt;p&gt;履歴に入っていた画像は、自作ソフトウェアの表示確認中に生成したものです。&lt;/p&gt;
&lt;p&gt;そのPNG生成処理を確認すると、IDATへ非圧縮のDEFLATEブロックを書き出していました。&lt;/p&gt;
&lt;p&gt;40枚のうち22枚は、1枚あたり約1.92 MBあります。800×600の画像としてはかなり大きいですが、画素データをほぼそのままPNGへ詰めているので、このサイズになります。&lt;/p&gt;
&lt;p&gt;画像表示ツールへ渡したあとも、そのPNGがBase64へ変換され、セッション履歴へ保存されていました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;無圧縮に近いPNGを生成
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ↓
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;画像表示ツールへ渡す
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ↓
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Base64 data URLとして履歴へ入る
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ↓
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;長期セッション内で画像が積み上がる
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;同じ画像がcompact後の履歴にも残るため、長く使っているうちにセッション全体も大きくなっていました。&lt;/p&gt;
&lt;h2 id="サイズだけが原因とはまだ言えない"&gt;サイズだけが原因とはまだ言えない&lt;/h2&gt;
&lt;p&gt;画像が履歴の大部分を占めているので、原因はこれに見えます。&lt;/p&gt;</description></item></channel></rss>