Claude Code エラー復旧パターン集——タスク失敗から立ち直る7つのテクニック

Claude Code エラー復旧パターン集——タスク失敗から立ち直る7つのテクニック

Claude Codeで本当に詰まったときの復旧手順を実体験ベースでまとめた。セッションクラッシュ・無限ループ・permission暴走・context overflow・ファイル破壊・bg agent暴走・コスト異常検知まで、7つのシナリオ別に具体的な復旧コマンドと設計を解説。

エンジニアのゆとです。

「あ、終わった」と思う瞬間が、Claude Codeには何種類かある。

ターミナルが突然落ちる。同じファイルをClaudeが永遠に書き直し続ける。Editツールがスタックして応答しなくなる。git履歴がどこに消えたかわからない。バックグラウンドエージェントが意図しないAPIを叩き続けてコストが溶けていく。

どれも一度経験すると、「次はどう止めるか」が刷り込まれる類の失敗だ。

この記事は、そういう「詰まった」経験から積み上げた復旧パターンの記録。体系的なチュートリアルじゃなくて、現場で使えるリカバリ手順集として書いた。Claude Codeをガチで使っている人の参考になれば。

なお、セッション再開の基本(--resume フラグの使い方)は別記事にまとめているので、そちらも合わせて読んでほしい。

Claude Code の --resume でセッションを復元する——クラッシュ後のリカバリと複数セッション管理の実践
Claude Code の --resume でセッションを復元する——クラッシュ後のリカバリと複数セッション管理の実践Claude Code の --resume フラグと会話履歴管理を徹底解説。クラッシュ後のセッション再開、セッションIDの特定方法、CLAUDE.md を使った状態の永続化、複数セッション並列管理まで実装例付きで解説。読む →

CCで「あ、終わった」となる瞬間

最初に、どういうシナリオで詰まるかを整理しておく。

対処法を知っている状態では「よくあること」で済むが、初めて直面するとパニックになりやすい。

セッションクラッシュ系

  • ターミナルのウィンドウを閉じた
  • 接続タイムアウト
  • macOSのスリープで接続が切れた
  • ネットワーク断

エージェント暴走系

  • 同じツール呼び出しを繰り返す無限ループ
  • permission確認を無視して勝手に進む
  • バックグラウンドエージェントが制御不能

データ破壊系

  • 意図しないファイルの書き換え
  • git commitまで自動で進まれた
  • .envや認証情報を変更された

リソース系

  • context windowが99%に達して応答が鈍くなる
  • APIコストが急増している
  • トークンの無駄遣いが止まらない

これらそれぞれに、有効な復旧経路がある。順番に見ていく。


パターン1: セッションクラッシュからの復旧

症状: ターミナルが落ちた。claude で起動しても最初からになる。

復旧手順:

# 直近セッションを再開(引数なしで最新を復元)
claude --resume

# セッションIDを指定して再開
claude --resume <session-id>

# 利用可能なセッション一覧を確認
ls -lt ~/.claude/projects/$(pwd | sed 's|/|-|g' | sed 's|^-||')/

セッションIDはプロジェクトディレクトリ配下のJSONLファイル名と対応している。ls -lt で新しい順に並べると、直近のセッションファイルがすぐ見つかる。

注意点: --resume はあくまで会話履歴を復元するだけで、「何をやっていたか」の文脈はClaudeが再推論する。未保存だった中間成果物(変数、一時ファイル等)は失われている。

予防策: CLAUDE.mdに「セッション開始時にやること」を書いておく。

## セッション開始時
- 前回の作業内容を memory/session_log.md から読む
- 変更中のファイルがあれば git status で確認してから着手

パターン2: 無限ループの脱出

症状: ClaudeがあるツールまたはファイルをN回繰り返し呼び出している。止める方法がわからない。

即時対応:

Ctrl+C

まずこれ。CCはシグナルを受け取ると現在のツール呼び出しを中断する。ただし何を途中まで実行したかは確認が必要。

PreToolUse hookで予防的に止める:

.claude/hooks/loop_guard.sh として保存:

#!/usr/bin/env bash
# PreToolUse hook — 同一ツール+同一引数の連続呼び出しを検出してブロック
# stdinからJSONを受け取る
INPUT=$(cat)
TOOL=$(echo "$INPUT" | jq -r '.tool_name')
FILE=$(echo "$INPUT" | jq -r '.tool_input.file_path // ""')

STATE_DIR="$HOME/.claude/loop_guard"
mkdir -p "$STATE_DIR"

KEY="${TOOL}__${FILE}"
KEY_HASH=$(echo -n "$KEY" | md5)
STATE_FILE="$STATE_DIR/$KEY_HASH"

if [ -f "$STATE_FILE" ]; then
  COUNT=$(cat "$STATE_FILE")
  COUNT=$((COUNT + 1))
  echo $COUNT > "$STATE_FILE"
  if [ "$COUNT" -ge 4 ]; then
    echo "LOOP DETECTED: $TOOL on $FILE called ${COUNT} times in a row. Blocking." >&2
    exit 2
  fi
else
  echo 1 > "$STATE_FILE"
fi

exit 0

settings.json に登録:

{
  "hooks": {
    "PreToolUse": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "bash .claude/hooks/loop_guard.sh"
          }
        ]
      }
    ]
  }
}

exit 2 でブロックすると、Claudeはその理由をstderrから読んで「なぜ止まったか」を自分で考える。繰り返しを認識させる効果がある。

ループ検出後のリセット:

rm -rf ~/.claude/loop_guard/

ループガードの状態を消去して、次のセッションからクリーンに動かす。


パターン3: permission暴走の止め方

症状: Claudeが確認なく連続してファイルを書き換えている。止めたいが確認ダイアログが来ない。

まず現状把握:

git status
git diff --stat

何が変更されたかを確認してから判断する。慌てて Ctrl+C する前に、現在の変更内容を把握するのが先。

--dangerously-skip-permissions を使っている場合:

これがオンだと全確認がスキップされる。セッションを一度終了して再起動するしかない。

# 再起動(permissionフラグなし)
claude

設定ファイルでのpermission制御:

~/.claude/settings.json または .claude/settings.json に以下を追加すると、特定の操作を常に確認必須にできる:

{
  "permissions": {
    "allow": [
      "Read(*)",
      "Bash(git status)",
      "Bash(git diff*)"
    ],
    "deny": [
      "Bash(git push*)",
      "Bash(rm -rf*)",
      "Bash(curl*)",
      "Bash(wget*)"
    ]
  }
}

deny に入っているコマンドはClaudeが実行しようとするとブロックされる。暴走を事前に防ぐ設計。

詳細なpermission設定については別記事を参照してほしい。

Claude Codeのパーミッションプロンプトを設計する——allowlistとsettings.jsonで確認頻度を最適化する
Claude Codeのパーミッションプロンプトを設計する——allowlistとsettings.jsonで確認頻度を最適化するClaude Codeのパーミッションプロンプトが頻繁に出て作業が止まる問題を解決する。settings.jsonのallowlist設定、プロジェクト別権限とグローバル権限の使い分け、危険コマンドは残しつつ安全なコマンドを通す設計パターンを実装例付きで解説。読む →

パターン4: context overflowからの復活

症状: 長時間作業後に応答が遅くなった。または「context window が逼迫しています」と警告が出た。

即時確認:

セッション内で /status を打つと現在のtoken使用量が出る。

軽度の場合(70〜85%): /compact

/compact

これはClaude Codeの組み込みコマンド。長い会話履歴を要約して圧縮し、context spaceを確保する。圧縮後も文脈は残る。

ただし、/compact は「これまでの会話をまとめた要約」に置き換えるので、細かい実装の詳細が失われることがある。精度に敏感なタスク(デバッグ中、複雑なリファクタリング中等)では使い所を選ぶ。

重度の場合(90%以上): セッション分割

新しいセッションを起動して、必要な文脈だけを引き継ぐ。引き継ぎのテンプレートを用意しておくと楽:

# context引き継ぎ用のサマリーを吐かせる
claude "現在の作業状態、完了したこと、残っているタスクをmarkdownで書いてください"
# → 出力を clipboard にコピーして新セッションに貼る

1Mコンテキストでも詰まる理由と対策については別記事で詳しく書いた:

Claude Code 1Mコンテキストの賢い使い方——トークン枯渇を防ぐ3層管理戦術
Claude Code 1Mコンテキストの賢い使い方——トークン枯渇を防ぐ3層管理戦術Sonnet 4.6/Opus 4.7で標準化した1Mコンテキストの落とし穴と管理戦術を実測データで解説。全部入れれば賢くなると思ったら逆だった話、3層管理の設計、/compactの最適タイミング、Python計測スクリプトまで。読む →

パターン5: 編集中ファイルの破壊からの戻し方

症状: Claudeが意図しない変更をファイルに加えた。元に戻したい。

まずgit diffで差分確認:

git diff
git diff --stat

シナリオ別の復元方法:

ケース1: まだgit addしていない(working tree上の変更)

# 特定ファイルを最後のコミット状態に戻す
git checkout -- src/components/SomeComponent.tsx

# 全ファイルを戻す(破壊的操作。確認してから)
git checkout -- .

ケース2: git addまでしてしまった(staging済み)

# ステージングから外す
git reset HEAD src/components/SomeComponent.tsx

# ファイルを最後のコミット状態に戻す
git checkout -- src/components/SomeComponent.tsx

ケース3: git commitまで進んでしまった

# 直前のコミットを取り消す(working treeは保持)
git reset --soft HEAD~1

# コミットと変更を両方取り消す(破壊的。慎重に)
git reset --hard HEAD~1

ケース4: 複数コミット前から変更されていた

# 変更の履歴を確認
git log --oneline -10

# 特定コミット時点のファイルを復元
git checkout <commit-hash> -- src/components/SomeComponent.tsx

予防策: PreToolUse hookで大規模変更を警告

#!/usr/bin/env bash
# .claude/hooks/large_edit_guard.sh
INPUT=$(cat)
TOOL=$(echo "$INPUT" | jq -r '.tool_name')

if [ "$TOOL" = "Edit" ] || [ "$TOOL" = "Write" ]; then
  FILE=$(echo "$INPUT" | jq -r '.tool_input.file_path // ""')
  if [ -f "$FILE" ]; then
    LINES=$(wc -l < "$FILE")
    if [ "$LINES" -gt 200 ]; then
      echo "Warning: editing large file ($LINES lines). Proceed with caution." >&2
      # exit 2 にするか exit 0 にするかはプロジェクトポリシーで決める
    fi
  fi
fi
exit 0

パターン6: バックグラウンドエージェント暴走の停止

症状: /schedule で登録したエージェントや、--bg で起動したエージェントが制御不能になった。

稼働中のagentプロセスを確認:

# Claudeプロセスを列挙
ps aux | grep "claude" | grep -v grep

# Claude Code関連プロセス全体
pgrep -la claude

特定のプロセスを止める:

kill <PID>

# 止まらない場合
kill -9 <PID>

LaunchAgentで管理しているエージェントを止める:

# 特定のエージェントを停止
launchctl unload ~/Library/LaunchAgents/com.myproject.agent.plist

# 再起動しないよう、plistをdisabledディレクトリに退避
mkdir -p ~/Library/LaunchAgents/_disabled/
mv ~/Library/LaunchAgents/com.myproject.agent.plist ~/Library/LaunchAgents/_disabled/

launchctl unload だけでは KeepAlive: true の設定があると再起動してしまう。plistを退避してから止めるのが確実。

スケジュールエージェントの停止(CCセッション内から):

セッション内で /schedule list を打つと登録済みのスケジュールが出る。/schedule cancel <id> でキャンセルできる。


パターン7: コスト異常検知と対応

症状: APIコストが急増している。何が原因かわからない。

まず使用量を確認:

Anthropicのダッシュボード(console.anthropic.com)でUsageを確認するのが一番確実。リアルタイムに近い粒度で出る。

ローカルでの使用量追跡スクリプト:

Claude Codeのセッションログ(~/.claude/projects/配下のJSONL)から、セッションごとのtoken数を集計できる。

#!/usr/bin/env python3
"""claude_cost_check.py — セッションログからtoken使用量を集計"""
from __future__ import annotations
import json
import os
from pathlib import Path
from datetime import datetime, timedelta

PROJECTS_DIR = Path.home() / '.claude' / 'projects'
# Sonnet 4.6の料金(2026-04時点)
INPUT_COST_PER_1M = 3.0   # $3 / 1M tokens
OUTPUT_COST_PER_1M = 15.0  # $15 / 1M tokens

def analyze_sessions(days: int = 7) -> None:
    cutoff = datetime.now() - timedelta(days=days)
    total_input = 0
    total_output = 0
    session_count = 0

    for project_dir in PROJECTS_DIR.iterdir():
        if not project_dir.is_dir():
            continue
        for jsonl_file in sorted(project_dir.glob('*.jsonl'), reverse=True):
            mtime = datetime.fromtimestamp(jsonl_file.stat().st_mtime)
            if mtime < cutoff:
                continue
            session_count += 1
            with open(jsonl_file) as f:
                for line in f:
                    try:
                        entry = json.loads(line)
                        usage = entry.get('usage', {})
                        total_input += usage.get('input_tokens', 0)
                        total_output += usage.get('output_tokens', 0)
                    except (json.JSONDecodeError, KeyError):
                        continue

    input_cost = total_input / 1_000_000 * INPUT_COST_PER_1M
    output_cost = total_output / 1_000_000 * OUTPUT_COST_PER_1M
    total_cost = input_cost + output_cost

    print(f"過去{days}日間の使用量")
    print(f"  セッション数: {session_count}")
    print(f"  Input tokens: {total_input:,}")
    print(f"  Output tokens: {total_output:,}")
    print(f"  推定コスト: ${total_cost:.2f}")
    print(f"    (Input: ${input_cost:.2f}, Output: ${output_cost:.2f})")

if __name__ == '__main__':
    analyze_sessions(days=7)

コスト異常の主な原因と対策:

原因兆候対策
無限ループoutput_tokensが異常に多いパターン2のloop guardを適用
大きなファイルの繰り返し読み込みinput_tokensが異常に多い.claudeignore でサイズ大ファイルを除外
バックグラウンドエージェントの暴走使った覚えのない時間帯にスパイクパターン6で停止、LaunchAgent確認
contextが大きすぎる全セッションで入力tokenが多い/compact の頻度を上げる、context分割

.claudeignore で無駄なtokenを削減:

# ビルド成果物
dist/
build/
.next/
.nuxt/

# 大きな静的ファイル
*.png
*.jpg
*.mp4
*.zip

# パッケージ
node_modules/
vendor/
__pycache__/

# ログ
*.log
logs/

予防策設計: CLAUDE.mdとHooksの組み合わせ

エラー復旧より「そもそも詰まらない設計」のほうが重要。7つのパターンから共通する予防策を整理する。

CLAUDE.mdに書くべき3つのこと:

## 作業開始前の確認
- git status で現在の変更状態を確認する
- ~/.claude/loop_guard/ を削除してループガードをリセット
- context使用量を /status で確認する(80%超えなら /compact してから着手)

## 禁止操作
- git push --force は絶対にやらない
- .env / .env.secrets への書き込みは人間が確認後のみ
- 本番データベースへの直接操作は禁止

## クラッシュ時の復旧手順
1. claude --resume で直近セッションを再開
2. git status / git diff で変更内容を確認
3. memory/session_log.md を読んで文脈を把握
4. 中断していたタスクから再開

必須hookの最小セット:

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "bash .claude/hooks/dangerous_command_guard.sh"
          }
        ]
      }
    ],
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "bash .claude/hooks/auto_git_checkpoint.sh"
          }
        ]
      }
    ]
  }
}

auto_git_checkpoint.sh の中身:

#!/usr/bin/env bash
# ファイル編集のたびにgitのworking treeをログに残す
# (コミットはしない。checkpoint stashで復元ポイントを作る)
INPUT=$(cat)
FILE=$(echo "$INPUT" | jq -r '.tool_input.file_path // ""')

if [ -n "$FILE" ] && [ -f "$FILE" ]; then
  # stashで中間状態を保存(メッセージ付き)
  TIMESTAMP=$(date '+%Y%m%d-%H%M%S')
  git stash push -m "checkpoint-$TIMESTAMP" -- "$FILE" 2>/dev/null || true
  # stashした後は元のworking treeに戻す(stashはあくまでバックアップ)
  git stash pop 2>/dev/null || true
fi
exit 0

厳密に言うと stash → pop をすると結局何も変わらないのだが、これで「いつでも git stash list で変更履歴を辿れる」という安心感が生まれる。実際には git stash drop しながらキレイに管理するか、単純に git add -p を定期的にやる方が現実的かもしれない。


復旧スクリプト集

よく使う復旧コマンドをワンライナーでまとめておく。コピペで使えるようにした。

# === セッション系 ===

# 直近セッション再開
claude --resume

# プロジェクトの全セッション一覧
ls -lt ~/.claude/projects/$(pwd | tr '/' '-' | sed 's/^-//') 2>/dev/null

# === git系 ===

# 現在の変更を確認
git status && git diff --stat

# 特定ファイルを最後のコミットに戻す
git checkout -- <file>

# 直前のコミットを取り消す(変更はkeep)
git reset --soft HEAD~1

# 直前のコミットと変更を取り消す(要注意)
git reset --hard HEAD~1

# === プロセス系 ===

# Claudeプロセス確認
ps aux | grep claude | grep -v grep

# 全Claudeプロセス停止
pkill -f "claude"

# LaunchAgent停止(KeepAlive対応)
launchctl unload ~/Library/LaunchAgents/com.xxx.plist && \
  mv ~/Library/LaunchAgents/com.xxx.plist ~/Library/LaunchAgents/_disabled/

# === ループガード系 ===

# ループガード状態クリア
rm -rf ~/.claude/loop_guard/

# === context系 ===

# セッション内コマンド(claudeセッション内で実行)
# /compact       — context圧縮
# /status        — token使用量確認
# /schedule list — 登録済みスケジュール確認

ハマりどころ

経験上、詰まりやすいポイントをまとめておく。

git reset --hard は最終手段

変更が消える。使う前に git stashgit diff > backup.patch で退避してから。--hard を使うなら本当に「全部捨てていい」を確認してから。

hookが動いていないと思ったら実行権限を確認

chmod +x .claude/hooks/*.sh

これを忘れると permission denied で静かに失敗する。hookが発火しているかどうかは、exit 0 の前に echo "hook triggered" >&2 を書いてデバッグするとわかる。

--resume はファイルの状態を復元しない

セッションの会話履歴だけが戻る。作業中のファイルは git stash listgit log を見て手動で把握し直す必要がある。「再開したのに文脈がない」と感じたら、CLAUDE.mdに状態ログの書き込みを習慣化するのが近道。

バックグラウンドエージェントのログ確認

LaunchAgentで動かしているエージェントのログは出力先を設定していないとどこにも残らない。plistに以下を書いておくとデバッグが楽になる:

<key>StandardOutPath</key>
<string>/tmp/com.myagent.stdout.log</string>
<key>StandardErrorPath</key>
<string>/tmp/com.myagent.stderr.log</string>

まとめ

7つのパターンをまとめると:

  1. セッションクラッシュ → claude --resume + CLAUDE.mdでの状態ログ習慣化
  2. 無限ループ → Ctrl+C + PreToolUse hookでの自動ブロック
  3. permission暴走 → settings.jsonのdenyリスト設計
  4. context overflow → /compact または /status でのモニタリング
  5. ファイル破壊 → git checkoutやgit resetによる段階的復元
  6. bg agent暴走 → plist退避付きのlaunchctl unload
  7. コスト異常 → ログからのtoken集計 + .claudeignore での予防

どのパターンも「詰まった後に何をするか」より「どう設計すれば詰まりにくいか」のほうが本質だ。

CLAUDE.mdで禁止操作を明示する、PreToolUse hookで危険な操作に待ったをかける、定期的にgitで状態を残す——この3つを最低限やっておけば、大抵のエラーはリカバリできる範囲に収まる。

ターミナルが落ちても、ループが走っても、「あ、終わった」ではなく「またか、どのパターンだっけ」と思えるようになったら、Claude Codeとの付き合い方が一段落ち着いてくる。


Claude Code Hooksで開発を自動化する — 実際に使える5パターンを解説【2026年版】
Claude Code Hooksで開発を自動化する — 実際に使える5パターンを解説【2026年版】Claude Code Hooksの設定方法と実践的な使い方を解説。PreToolUse・PostToolUse・SessionStart・Notificationなど主要イベントを使った自動化レシピ5選。副業・フリーランスエンジニア向けに実用性重視でまとめた。読む →
Claude Code の --resume でセッションを復元する——クラッシュ後のリカバリと複数セッション管理の実践
Claude Code の --resume でセッションを復元する——クラッシュ後のリカバリと複数セッション管理の実践Claude Code の --resume フラグと会話履歴管理を徹底解説。クラッシュ後のセッション再開、セッションIDの特定方法、CLAUDE.md を使った状態の永続化、複数セッション並列管理まで実装例付きで解説。読む →
← 記事一覧に戻る