◉CLAUDE LABEN
●2.1.310 — Bedrock・Vertex・Foundry でも Monitor ツールが使え、ゲートウェイの失敗を修正しました(10/23)●2.1.307 — スリープやキーチェーンロックのあとに MCP が再接続されない問題を修正しました(10/21)。2.1.306 では claude -p の誤表示も解消●SONNET 4.5 — Claude API での提供終了は 11/30、残り36日。移行先は Sonnet 5.5●WINDOWS — 日本語の環境でだけフックが黙って壊れる報告があり、文字コードの確認が呼びかけられています●API — 新しい API バージョン 2026-10-21 では temperature・top_p・top_k を渡すと 400 になります●NEW — Cowork に渡したフォルダの先頭に、十行の約束ファイルを置いてみました●2.1.310 — Bedrock・Vertex・Foundry でも Monitor ツールが使え、ゲートウェイの失敗を修正しました(10/23)●2.1.307 — スリープやキーチェーンロックのあとに MCP が再接続されない問題を修正しました(10/21)。2.1.306 では claude -p の誤表示も解消●SONNET 4.5 — Claude API での提供終了は 11/30、残り36日。移行先は Sonnet 5.5●WINDOWS — 日本語の環境でだけフックが黙って壊れる報告があり、文字コードの確認が呼びかけられています●API — 新しい API バージョン 2026-10-21 では temperature・top_p・top_k を渡すと 400 になります●NEW — Cowork に渡したフォルダの先頭に、十行の約束ファイルを置いてみました
記事一覧/Claude Code
⟐ Claude Code/2026-06-09中級

前回の記事本文が別の記事に紛れ込む — 固定名の一時ファイルに残る残骸の罠

Claude Code の自動化で、固定名の一時ファイルに前回の中身が残り、まったく別の記事に古い本文が混入する。書き込みが無音で失敗する仕組みと、ユニーク名+挿入後の grep 照合で防ぐ方法を記録します。

troubleshooting62error15fix11claude-code132automation55shell

ある朝、公開済みの記事を読み返していて、背筋が冷たくなりました。Claude の MCP についての記事の本文に、前日に書いた git のエラー対処の段落が、まるごと紛れ込んでいたのです。タイトルと導入は正しいのに、本文の真ん中だけが別の記事だった——しかもエラーログには何も残っていませんでした。

赤い文字が出るバグなら、まだ気づけます。この種の事故が怖いのは、すべての処理が「成功」と報告したまま、中身だけがすり替わっている点です。原因は、自動化スクリプトが使っていた一時ファイルの「名前」にありました。

何が起きていたか — 本文だけが古い記事のもの

私の記事生成は、長い MDX 本文を一度シェル変数やヒアドキュメントに収めるのではなく、いったん一時ファイルに書き出してから、フロントマターと結合する作り方をしていました。素朴に書くと、こうなります。

# 本文を一時ファイルに書き出す
cat > /tmp/body.md << 'BODY'
(ここに今回の記事本文)
BODY
 
# フロントマターと結合して記事を組み立てる
cat frontmatter.md /tmp/body.md > "content/articles/ja/claude-code/${SLUG}.mdx"

一見すると問題はなさそうに見えます。ところが /tmp/body.md という名前が固定であることが、後で効いてきました。

複数の記事を1回の実行でまとめて生成していたとき、2本目の本文を書き出すステップが何らかの理由で失敗すると、/tmp/body.md には1本目の本文が残ったままになります。そして結合ステップはそのまま走り、2本目の記事に1本目の本文が入り込みました。

なぜ書き込みが「無音で」失敗するのか

cat > file << 'BODY' ... BODY のヒアドキュメントは、いくつかの条件で中身を書かずに終わります。しかも多くの場合、致命的なエラーを大きく出さずに通り過ぎます。

ひとつは、ヒアドキュメントの終端マーカーがずれるケースです。本文の中にたまたま BODY という行が含まれていたり、インデント付きで終端を書いていたりすると、シェルは終端を見失い、途中までしか書き込まないか、空のまま終わります。

ディスク容量の枯渇も典型です。書き込み中に空き容量がなくなると、ファイルは中途半端な状態で閉じられます。サンドボックスや CI の /tmp は容量が小さいことが多く、ここは特に踏みやすい地雷でした。容量まわりの切り分けはENOSPC でディスクが足りなくなったときの対処に詳しくまとめています。

権限の問題もあります。/tmp の所有者がプロセスと異なると書き込めず、けれど古いファイルは読めてしまう、という状況が起こり得ます。この所有権まわりは/tmp が書き込めないときに $HOME/repos へ退避する方法で扱いました。

共通しているのは、書き込みが失敗しても、その前に存在したファイルは消えずに残るという点です。cat > は書き込みに入る前にファイルを切り詰めますが、途中で失敗すれば中途半端な内容が、あるいはリダイレクト自体が走らなければ前回の内容が、そのまま居座ります。次のステップはファイルの「鮮度」を確認しないので、古い残骸を平然と読み込みます。

再現してみる

挙動を手元で確かめると、対策の勘所がつかめます。固定名のファイルに古い内容を残したまま、次の書き込みをわざと失敗させてみます。

# 1本目の本文を書き出す
echo "OLD ARTICLE BODY" > /tmp/body.md
 
# 2本目の書き込みを、存在しないディレクトリ経由でわざと失敗させる
cat > /tmp/nowhere/body.md << 'BODY' 2>/dev/null
NEW ARTICLE BODY
BODY
echo "write exit code: $?"   # 1 が返る(でもスクリプトは止まらない)
 
# 鮮度を確認せずに /tmp/body.md を読むと…
cat /tmp/body.md             # → OLD ARTICLE BODY が出てくる

書き込みに失敗した(終了コードが 1)にもかかわらず、結合ステップが /tmp/body.md を読めば、古い本文が混ざります。set -e を付けていても、リダイレクト先のパスが別ファイルなら /tmp/body.md の残骸検出には役立ちません。

対処 — 「名前を毎回変える」と「書いた中身を照合する」

私が落ち着いたのは、二つの原則を組み合わせる方法です。発生を防ぐ「ユニーク名」と、起きても気づける「挿入後の照合」です。

1. 一時ファイルにスラッグを含むユニーク名を付ける

固定名をやめ、記事のスラッグ(と必要なら乱数)を含む名前にします。そもそも前回の残骸と同じパスにならなければ、混入は構造的に起こりません。置き場所も、容量と所有権が安定している $HOME 配下に移します。

# 記事ごとに固有のパスを作る。固定名 /tmp/body.md は使わない
WORKDIR="$HOME/.cache/article-build"
mkdir -p "$WORKDIR"
BODY_FILE="$WORKDIR/${SLUG}.body.md"
 
# 念のため、組み立て前に古いファイルを必ず消す
rm -f "$BODY_FILE"
 
cat > "$BODY_FILE" << 'BODY'
(今回の記事本文)
BODY

mktemp を使うのも有効です。BODY_FILE=$(mktemp) なら衝突しない一時ファイルを確実に得られます。ただし自動化では、どの記事に対応するファイルか後から追えるよう、スラッグを名前に埋めておくほうがログを追いやすいと感じています。

2. 書き込み直後に「終了コード」と「中身」を二重で確認する

ユニーク名にしても、書き込み自体が失敗していれば空ファイルや中途半端なファイルが残ります。だから書いた直後に、終了コードとファイルの中身の両方を見ます。

cat > "$BODY_FILE" << 'BODY'
(今回の記事本文)
BODY
STATUS=$?
 
# (a) 終了コードを確認する
if [ "$STATUS" -ne 0 ]; then
  echo "❌ 本文の書き込みに失敗しました(exit $STATUS)"
  exit 1
fi
 
# (b) 空でないこと、今回のスラッグ固有の語が含まれることを照合する
if [ ! -s "$BODY_FILE" ]; then
  echo "❌ 本文ファイルが空です: $BODY_FILE"
  exit 1
fi
if ! grep -q "今回の記事を一意に表すフレーズ" "$BODY_FILE"; then
  echo "❌ 期待した本文が入っていません。前回の残骸の可能性があります"
  exit 1
fi

3. 組み立て後の MDX も grep で照合する

仕上げに、結合してできた MDX が「正しい記事」になっているかを確認します。フロントマターの title や slug に対応するキーワードが本文側にも現れているか、逆に別記事に固有の語が混ざっていないかを見ます。

OUT="content/articles/ja/claude-code/${SLUG}.mdx"
 
# slug がフロントマターと本文の整合チェックに使える
if ! grep -q "slug: \"${SLUG}\"" "$OUT"; then
  echo "❌ 生成された MDX の slug が一致しません"
  exit 1
fi
 
# 直前に生成した別記事の固有語が紛れていないか(任意)
PREV_MARKER="前の記事に固有の見出し語"
if grep -q "$PREV_MARKER" "$OUT"; then
  echo "❌ 別記事の本文が混入している可能性があります"
  exit 1
fi

この push 直前の grep ガードという考え方は、SKILL.md に push 前 grep ガードを仕込む話で別の角度からも書きました。検索が空振りするときの落とし穴はgrep が結果ゼロを返すときの切り分けも合わせて読んでいただけると、照合の精度を上げられます。

自動化では「状態を引き継ぐファイル」をいちばん疑う

この一件で改めて感じたのは、自動化で最も危ういのは、複数の実行をまたいで生き残るファイルだということです。固定名の一時ファイルは、便利な反面、前回の状態を黙って次へ運んでしまいます。git push が何もしなくても成功するのと同じで、ファイルの「鮮度」もまた、コマンドの成功とは別の次元の問題です。終了コードだけを信じて止まっていた失敗の話は、git push が成功表示なのに反映されない罠にもまとめています。

アーティスト・クリエイターの廣川政樹です。2014年から個人開発を続けて、累計5,000万ダウンロードを超えるアプリ運営と、4つの技術ブログ(Dolice Labs)の自動更新を並行しています。手を動かして何かを作るとき、いちばん怖いのは派手な失敗ではなく、静かに正しくないものが出来上がっていることだと、宮大工だった祖父の仕事を思い出すたびに感じます。だからこそ、書いたはずの中身が本当にそこにあるかを、仕組みとして確かめておきたいのです。

まずは、自動化スクリプトの固定名の一時ファイルを一つ探して、スラッグ入りのユニーク名に変え、書き込み直後に grep -q を一行足してみてください。次に「成功ログ」が出たとき、その中身まで含めて信じられるようになります。

最後までお読みいただき、ありがとうございました。同じ無音のすり替えで青ざめる方が、一人でも減れば嬉しいです。

シェア

お読みいただきありがとうございます

Claude Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • ✦コピー&ペーストで使える実装コード付き
  • ✦毎日新しい上級ガイドを追加
  • ✦¥580/月 または ¥1,480 の永久アクセス
メンバーシップを見る →

もしこの記事がお役に立ちましたら、チップ(¥150)で応援いただけると大変励みになります。広告なしでの運営を続けるため、皆さまのご支援が大きな力になっています。

関連記事

⟐ Claude Code2026-05-02
Claude Code の Edit が弾かれる二つの理由 — 複数一致と、見つからない場合の切り分け
Claude Code の Edit ツールが失敗する原因は、「一致する箇所が複数ある」と「一致する箇所が見つからない」の二つに分かれます。それぞれの見分け方と、old_string の作り方、整形・改行コード・不可視文字の確かめ方を、手元の失敗例から書き残しました。
⟐ Claude Code2026-05-24
Claude Code で連続する Edit が連鎖的に失敗するときの直し方 — old_string が消える・重複する問題
Claude Code が同じファイルへ Edit を続けて投げると、2件目以降が『not found』『not unique』『modified since read』で落ちることがあります。エラー別の原因と、一致件数を先に数える小さなスクリプト、フォーマッタ Hook の正しい設定をまとめます。
⟐ Claude Code2026-05-10
Claude Code の Glob と Grep が0件を返すときの原因切り分け
Claude Code の Glob や Grep が 0 件を返したとき、ファイルがあるのに見えない理由を、除外ルール・隠しフォルダ・パターン記法・作業範囲の順に切り分けます。ターミナルの find と rg で事実を先に確かめる手順と、最初の依頼文に添える一文まで、実際にハマった順に書き残します。