Error Recovery: Handling Failures and Getting Unstuck
Claude just refactored your authentication module. It touched six files, updated the tests, and then — the type checker shows 23 errors. The tests that were passing five minutes ago now fail across three test suites. Claude tries to fix the errors but introduces new ones. You are two iterations deep into a fix-the-fix spiral and the codebase is worse than when you started. You need to get back to a known good state, understand what went wrong, and try again with a better approach.
This guide covers every recovery mechanism Claude Code gives you: checkpoints for undoing edits, session management for restarting cleanly, strategies for breaking out of error loops, and workflows for preventing cascading failures in the first place.
What You’ll Walk Away With
Section titled “What You’ll Walk Away With”- The Esc-Esc checkpoint rewind that undoes Claude’s changes instantly
- A workflow for recovering from cascading test failures without losing progress
- Strategies for breaking Claude out of fix-the-fix loops
- Context management techniques when sessions get too long
- Preventive patterns that reduce the need for recovery in the first place
The Checkpoint System
Section titled “The Checkpoint System”Every time Claude edits a file, it snapshots the previous contents before making changes. These checkpoints are your safety net.
Reverting with Esc-Esc
Section titled “Reverting with Esc-Esc”The fastest recovery: press Esc twice. This opens the checkpoint rewind interface, letting you scroll back through Claude’s edits and restore any previous state. Each checkpoint shows what changed, so you can pick exactly which point to revert to.
This is separate from git. You do not need to have committed anything. Checkpoints cover all file edits Claude made during the current session.
# After pressing Esc twice, you see something like:# [3] Edited src/lib/auth.ts - refactored session handler# [2] Edited src/lib/auth.ts - added rate limiting# [1] Edited src/api/routes/login.ts - updated login handler## Select a checkpoint to revert to that stateAsking Claude to Undo
Section titled “Asking Claude to Undo”If you prefer to stay in the conversation:
Undo the last change you made to src/lib/auth.ts.Or to undo everything from a specific action:
Undo all the changes from the authentication refactor.Revert every file you touched back to how it was before.Breaking Out of Fix-the-Fix Loops
Section titled “Breaking Out of Fix-the-Fix Loops”The most common failure mode: Claude introduces an error, tries to fix it, introduces a new error, fixes that, and the code gets progressively worse with each iteration. Here is how to break out.
Stop and Assess
Section titled “Stop and Assess”The moment you notice Claude is going in circles, interrupt:
Stop. Do not make any more changes. The last three attempts havemade things worse. Let me assess where we are.Then ask Claude to evaluate the current state without making edits:
This forces Claude to reason about the problem instead of reactively patching symptoms.
Revert and Retry
Section titled “Revert and Retry”Sometimes the cleanest path forward is to undo everything and start over with a different approach:
Revert all changes from this session. Then let us try a differentapproach to the authentication refactor. Instead of restructuringthe entire module, change only the session handling logic andleave the rest untouched.A fresh attempt with a narrower scope almost always produces better results than trying to salvage a broken refactor.
Give Claude a Different Direction
Section titled “Give Claude a Different Direction”If Claude keeps failing with the same strategy, redirect explicitly:
Stop trying to fix the type error by changing the interface.Instead, update the implementation in auth-service.ts to matchthe existing interface. The interface is correct; theimplementation is wrong.Claude often needs you to tell it which side of a conflict is authoritative. Without direction, it may keep oscillating between changing the interface and changing the implementation.
Recovering from Test Failures
Section titled “Recovering from Test Failures”Diagnosing Cascading Failures
Section titled “Diagnosing Cascading Failures”When multiple tests fail after a change, the failures are usually connected. Ask Claude to find the root cause:
This prevents Claude from trying to fix each test individually, which often leads to inconsistent patches across test files.
The Incremental Recovery Pattern
Section titled “The Incremental Recovery Pattern”When you have many failures, recover incrementally:
-
Run the type checker first — Type errors are the most common root cause of test failures after a refactor. Fix these before even looking at test results.
-
Run one test file at a time — Start with the test file closest to the code you changed. Fix that before moving to dependent test files.
-
Verify after each fix — Run the full suite after fixing each test file to see if the fix resolved failures elsewhere too.
-
Stop when green — Do not keep “fixing” tests that are already passing.
Run npx tsc --noEmit first. Fix all type errors. Then runthe tests for @src/lib/auth.test.ts only. Fix any failures.Then run the full suite to see what else cleared up.Managing Context Overload
Section titled “Managing Context Overload”Long sessions accumulate context: file reads, command outputs, failed attempts, backtracked approaches. Eventually Claude’s responses degrade because the important information is buried under noise.
Use /compact to Free Context
Section titled “Use /compact to Free Context”When Claude starts losing track of your project’s patterns or repeating earlier mistakes:
/compact focus on the authentication refactor and current test failuresThe /compact command summarizes the conversation and frees up context space. The focus argument tells Claude what to prioritize in the summary, so the important context survives compaction.
Start Fresh with /clear
Section titled “Start Fresh with /clear”If compaction is not enough, clear the entire conversation:
/clearThen immediately re-establish context:
I was working on refactoring the authentication module. Thecurrent state is:- I changed src/lib/auth.ts to use async session handling- The type checker passes- Two tests in auth.test.ts are still failing- The failures are related to mock setup for the new async functions
Read the failing tests and fix the mock setup.Break Long Tasks into Sessions
Section titled “Break Long Tasks into Sessions”If a task takes more than 30-40 minutes, break it into separate sessions rather than fighting context degradation:
- Session 1: Schema and database migration
- Session 2: API route implementation
- Session 3: Tests and integration
- Session 4: Review and PR
Start each session fresh with claude, not claude -c. Give Claude a brief summary of what was done in previous sessions and what the current task is.
Session Recovery
Section titled “Session Recovery”Continuing After a Crash
Section titled “Continuing After a Crash”If Claude Code exits unexpectedly, your conversation history is preserved. Resume with:
claude -cThis continues the most recent conversation. All previous messages and tool results are restored.
Forking a Session
Section titled “Forking a Session”If you want to try a different approach without losing your current session:
claude --continue --fork-sessionThis creates a new session with the same conversation history up to this point. The original session remains unchanged. You can try the alternative approach in the fork and go back to the original if it does not work.
Switching to a Different Session
Section titled “Switching to a Different Session”If you have multiple sessions from different attempts:
claude --resumeThis opens a session picker. Use B to filter by current branch, making it easy to find the session you want.
Preventive Patterns
Section titled “Preventive Patterns”The best recovery is not needing recovery. These patterns reduce failures before they happen.
Verify After Every Change
Section titled “Verify After Every Change”The single most effective habit:
After making each change, run the type checker and relevant tests.Do not move to the next step until the current step passes. Ifsomething fails, fix it before continuing.This catches errors when they are small and isolated, not after they have cascaded across the codebase.
Use Git Checkpoints
Section titled “Use Git Checkpoints”Before risky operations, create a git commit:
Commit the current working state with a message like"checkpoint: before auth refactor". Do not push this commit.If everything goes wrong, you can git reset --soft HEAD~1 to return to this point while keeping all the changes staged.
Narrow the Scope
Section titled “Narrow the Scope”Instead of “refactor the authentication module,” try “change only the session expiry logic in auth.ts, keeping the rest of the module unchanged.” Narrower scope means fewer files touched, fewer potential errors, and easier recovery.
Ask Claude to Explain Before Editing
Section titled “Ask Claude to Explain Before Editing”Before any complex change:
Before making changes, explain exactly what you plan to modifyand why. List every file you will touch and what the changewill be in each file.Catching a bad plan is much cheaper than reverting a bad implementation.
When This Breaks
Section titled “When This Breaks”Esc-Esc does not show checkpoints — Checkpoints only exist for the current session. If you started a new session, the checkpoints from the previous session are gone. Use git history to recover instead: git diff to see what changed, git checkout -- <file> to revert specific files.
Claude keeps repeating the same failed approach — Use /clear and start fresh. Describe the problem from scratch and explicitly rule out the approach that was not working: “Do not restructure the module. Instead, make the minimal change needed to fix the timeout issue.”
/compact loses important context — Add a focus argument: /compact focus on the database migration and the three remaining test failures. Without a focus, compaction may drop details you need. For critical context, add it to your CLAUDE.md so it persists across sessions.
Tests pass locally but Claude introduced subtle bugs — After any significant change, ask Claude to review its own work: “Review all changes you made in this session. Check for edge cases, null handling, and error paths that might be missing.” This self-review catches issues that tests miss.
Session becomes unusable due to context bloat — Start a new session with claude (not claude -c). Give Claude a brief summary and the specific files to read. Five minutes of re-establishing context is faster than fighting a degraded session for thirty minutes.
What’s Next
Section titled “What’s Next”You have now completed the Claude Code quick-start guide. You can install Claude Code, authenticate, configure permissions, set up your IDE, initialize your project with CLAUDE.md, plan features from a PRD, use extended thinking for hard problems, connect MCP servers, build features incrementally, manage version control, and recover from failures.