Clean Slate Recovery: Escaping Bad LLM Trajectories

James Phoenix
James Phoenix

Summary

When an LLM gets stuck repeating failed approaches, context rot has set in. Clean slate recovery solves this by starting a fresh session with explicit constraints about what didn’t work and why. This prevents the LLM from repeating failed paths and costs less than continuing a broken trajectory.

The Problem

After 3+ failed attempts at solving a problem, LLMs accumulate negative context (failed implementations, error messages, dead-end approaches) that pollutes future generations. The LLM gets stuck in a loop, repeatedly suggesting the same failed approaches or variations that still don’t work. The conversation context becomes a liability rather than an asset.

The Solution

Terminate the current session and start fresh with a clean context. In the new session, explicitly state: (1) what the previous approach was, (2) why it failed, and (3) constraints to avoid repeating the failure. This gives the LLM a fresh start while preserving the learning from failures, allowing it to explore new solution paths without negative context accumulation.

The Problem

You’re working with an AI coding agent, trying to fix a bug or implement a feature. The first attempt doesn’t work. Neither does the second. By the third attempt, you notice something troubling: the LLM keeps suggesting variations of approaches that have already failed.

This is context rot—the accumulation of negative context that poisons future generations.

How Context Rot Happens

LLMs are stateful within a conversation. Every failed attempt adds to the context:

Attempt 1: "Try using JWT refresh tokens"
→ Implementation fails
→ Error messages added to context
→ Failed code added to context

Attempt 2: "Let's modify the JWT approach"
→ Still fails
→ More error messages
→ More failed code
→ Context now contains 2 failed implementations

Attempt 3: "How about adjusting the JWT validation?"
→ Still fails
→ Even more errors
→ Context now polluted with 3 failed JWT attempts

Attempt 4: "Maybe we need to tweak the JWT expiration..."
→ You're stuck in a loop

The LLM is now anchored on the JWT approach because the entire conversation history is saturated with JWT-related attempts. It can’t easily escape to explore fundamentally different solutions.

The Cost of Continuing

Continuing a broken trajectory has real costs:

  1. Time cost: Each failed iteration takes 2-5 minutes
  2. Token cost: Large context windows with error messages are expensive
  3. Mental cost: Developer frustration compounds
  4. Opportunity cost: Better solutions go unexplored

After 3 failed attempts (15+ minutes), you’ve likely spent more time than starting fresh would take.

Recognition Signals

You know context rot has set in when:

  • Same approach, different variation: “Let’s try X… okay, how about X with Y… maybe X with Z?”
  • Circular reasoning: The LLM refers back to failed attempts as if they might work now
  • Error message accumulation: Context fills with stack traces and error logs
  • Decreasing suggestion quality: Later suggestions are worse than early ones
  • The “stuck” feeling: You sense the conversation is going nowhere

The Solution: Clean Slate Recovery

Clean slate recovery is a deliberate pattern for escaping bad trajectories.

The Pattern

1. Recognize trajectory is broken (3+ failed attempts)
2. Terminate current conversation/session
3. Start new session with clean context
4. Frame the problem with constraints:
   - "Previous approach: X"
   - "Why it failed: Y"
   - "Constraints: Must do A, cannot do B"
5. Let LLM explore fresh solution space

Why It Works

Clean context = fresh perspective

By removing negative context accumulation, the LLM can:

  1. Explore different solution branches not anchored to failed attempts
  2. Consider fundamentally different approaches without JWT/previous-solution bias
  3. Apply learning from failures through explicit constraints
  4. Generate with higher quality since context isn’t polluted

Learning without baggage

The key insight: You don’t need the failed implementations in context—you only need the lessons learned expressed as constraints.

❌ Bad (keeping failure context):
"Here's the JWT code that failed with error X...
And here's the modified JWT code that failed with error Y...
And here's another JWT variation that failed with error Z...
Can you try something else?"

✅ Good (clean slate + constraints):
"Implement authentication.

Context: Previous approach using JWT refresh tokens didn't work 
because our API doesn't support refresh endpoints.

Constraints:
- Must use session-based auth only
- Cannot modify backend API  
- Must handle 401 responses gracefully

Suggest an approach."

The second prompt gives the LLM all the information it needs to succeed, without the cognitive burden of processing failed attempts.

Implementation

Step 1: Recognize the Pattern

Set a 3-attempt threshold. If you haven’t made progress after 3 attempts, trigger clean slate recovery.

// Mental checklist
const shouldRestart = (
  attempts >= 3 &&
  (sameApproachRepeated || solutionQualityDeclining || feelingStuck)
);

if (shouldRestart) {
  // Time for clean slate
}

Step 2: Document What Failed

Before terminating the session, capture:

  1. What approach was tried
  2. Why it failed (root cause, not just symptoms)
  3. What constraints were violated
## Session 1 Learnings

Approach: JWT refresh token authentication

Failure reason: 
- API doesn't expose refresh token endpoint
- Cannot modify backend (external service)
- JWT approach requires refresh capability

Constraints discovered:
- Backend is read-only (cannot add endpoints)
- Must work with existing session-based auth
- Need to handle token expiration gracefully

Step 3: Start Fresh Session

Open a new conversation/session. This ensures:

  • Clean context window
  • No accumulated error messages
  • Fresh token budget
  • Psychological reset for both you and the LLM

Step 4: Frame with Constraints

Structure your prompt to include:

# Task
[Clear description of what you need]

# Context: Previous Approach
[One sentence: what was tried]

# Why It Failed  
[One sentence: root cause]

# Constraints
[Bullet list: what must/cannot be done]

# Request
[What you want the LLM to do]

Step 5: Verify New Direction

Before implementing, ask the LLM to:

  1. Confirm it understands the constraints
  2. Propose approach before writing code
  3. Explain why this approach avoids previous failures

This prevents immediately falling into another bad trajectory.

Examples

Example 1: Authentication Bug

Session 1 (Failed trajectory):

You: "Fix the authentication bug where users get logged out"

LLM: "Let's add JWT refresh tokens..."
→ Fails (API doesn't support refresh)

You: "That didn't work, API error"

LLM: "Try storing refresh token in localStorage..."
→ Fails (still no API endpoint)

You: "Still failing"

LLM: "Maybe we need to adjust the token validation..."
→ Fails (API design issue, not validation)

[Stuck in JWT refresh loop]

Session 2 (Clean slate recovery):

You: "Implement authentication that keeps users logged in.

Context: Previous approach tried JWT refresh tokens but failed because 
our API doesn't expose refresh endpoints and we cannot modify the backend.

Constraints:
- Must use session-based auth (API provides session cookies)
- Cannot modify backend API (external service)
- Must handle 401 responses by redirecting to login
- Should persist session across page refreshes

Suggest an approach."

LLM: "Since we're using session-based auth, we can:
1. Let the API handle session cookies (automatic)
2. Add axios interceptor to catch 401 responses  
3. On 401, clear local state and redirect to login
4. Sessions persist via httpOnly cookies (secure)

This avoids JWT refresh complexity and works with existing API."

→ Success! Completely different approach.

Example 2: Performance Optimization

Session 1 (Failed trajectory):

You: "Optimize the slow dashboard query"

LLM: "Add indexes on user_id and created_at..."
→ Marginal improvement (2.1s → 1.9s)

You: "Still too slow"

LLM: "Add composite index on (user_id, created_at, status)..."
→ Minimal improvement (1.9s → 1.8s)

You: "Not enough"

LLM: "Try adding index on organization_id too..."
→ No improvement (1.8s)

[Stuck in index-adding loop]

Session 2 (Clean slate recovery):

You: "Optimize slow dashboard query (currently 1.8s).

Context: Previous approach tried adding various indexes but only improved 
from 2.1s to 1.8s (14% improvement, not enough).

Why it failed: The query joins 5 tables and fetches 50+ columns. 
Indexes can't solve the fundamental issue of too much data transfer.

Constraints:
- Target: <200ms response time
- Cannot change database schema
- Can add caching, materialized views, or denormalization

Suggest approach."

LLM: "The issue is data transfer volume, not query planning. 
Suggestions:

1. Add materialized view for dashboard data (refreshed every 5 min)
2. Return only needed columns (currently fetching 50+, only show 8)
3. Add Redis cache for user-specific dashboard (5 min TTL)

This targets the root cause (too much data) rather than query planning."

→ Implementation: 1.8s120ms (93% improvement)

Example 3: Type Error Hell

Session 1 (Failed trajectory):

You: "Fix TypeScript errors in user service"

LLM: "Add type assertion: user as User..."
→ Errors persist

You: "Still failing"

LLM: "Try casting: (user as any) as User..."
→ Compiles but runtime errors

You: "Runtime errors now"

LLM: "Use type guard: if (isUser(user))..."
→ Doesn't solve underlying issue

[Stuck in type-casting loop]

Session 2 (Clean slate recovery):

You: "Fix type errors in user service.

Context: Previous attempts tried type assertions and casts but 
this just masked the underlying problem.

Why it failed: The API returns UserDTO but our code expects User. 
Type assertions don't solve the shape mismatch.

Constraints:
- Cannot change API response format
- Must maintain type safety (no 'any')
- Need runtime validation

Suggest approach."

LLM: "The issue is DTO-to-domain mapping. Solution:

1. Create explicit mapper: userDtoToUser(dto: UserDTO): User
2. Add runtime validation using zod schema
3. Call mapper at API boundary
4. Use proper User type everywhere else

This solves the shape mismatch properly instead of hiding it with casts."

→ Type-safe solution that handles the actual problem

Best Practices

1. Set a Threshold

Establish a 3-attempt rule:

Attempt 1: Try LLM's first suggestion
Attempt 2: Try refinement/variation
Attempt 3: Try alternative approach

If attempt 3 fails → Clean slate recovery

Don’t wait for 5-10 attempts. Early reset is cheaper.

2. Capture Root Cause, Not Symptoms

When documenting failures:

❌ Bad: "Got error: Cannot read property 'id' of undefined"
✅ Good: "API sometimes returns null instead of user object"

❌ Bad: "Authentication keeps breaking"
✅ Good: "JWT refresh requires /refresh endpoint which doesn't exist"

❌ Bad: "Query is slow"
✅ Good: "Query transfers 50+ columns but only 8 are displayed"

Root cause understanding prevents repeating the failure.

3. Be Specific with Constraints

❌ Vague: "Make it work with the existing API"
✅ Specific: "API provides session cookies via Set-Cookie header. 
              Cannot add new endpoints. Must use existing /login and /logout."

❌ Vague: "Fix the performance issue"
✅ Specific: "Target <200ms response. Can add caching/materialized views. 
              Cannot change database schema (production database)."

Specific constraints guide the LLM to viable solutions.

4. Verify Understanding First

Before implementation:

You: [Clean slate prompt with constraints]

LLM: [Proposes approach]

You: "Before implementing, confirm:
1. Does this approach satisfy all constraints?
2. Why won't this hit the same failure as the JWT approach?
3. What's the key difference from the previous failed attempts?"

LLM: [Explains reasoning]

You: "Great, proceed with implementation."

This verification step prevents immediately jumping into another bad trajectory.

5. Know When NOT to Reset

Don’t reset if:

  • Making steady progress (each attempt improves)
  • Only 1-2 attempts (too early)
  • Issue is environmental (wrong API key, network error)
  • You haven’t provided enough context (add context first, then retry)

Reset when:

  • Same approach variations (“try JWT… try JWT + X… try JWT + Y…”)
  • Quality declining (suggestions getting worse)
  • Circular references (“let’s go back to approach 1…”)
  • Feeling stuck (intuition is valuable)

Integration with Other Patterns

Combine with Trust But Verify Protocol

Before accepting an LLM suggestion in a new session:

  1. Verify it addresses the root cause
  2. Check it satisfies all constraints
  3. Confirm it’s not a variation of what failed

See: Trust But Verify Protocol

Combine with Plan Mode Strategy

Instead of implementing immediately after clean slate:

  1. Ask LLM to propose 2-3 approaches
  2. Evaluate approaches against constraints
  3. Select best approach
  4. Then implement

Iterating on plans is cheaper than iterating on implementations.

See: Plan Mode Strategy

Combine with Context Debugging Framework

If your tool supports it, use systematic debugging to prevent rot:

  1. Detect declining quality (test failure rate, same suggestions)
  2. Debug systematically (context → prompting → model power → manual)
  3. If debugging doesn’t help → Clean slate

See: Context Debugging Framework

Measuring Success

Success Metrics

Track clean slate recovery effectiveness:

interface RecoveryMetrics {
  oldSessionAttempts: number;        // How many attempts before reset
  oldSessionCost: number;            // Token cost of failed session
  newSessionAttempts: number;        // Attempts in new session to solve
  newSessionCost: number;            // Token cost of new session  
  totalTime: number;                 // Total time to solution
  solved: boolean;                   // Did clean slate solve it?
}

// Example
const metrics: RecoveryMetrics = {
  oldSessionAttempts: 5,             // 5 failed attempts
  oldSessionCost: 15000,             // 15K tokens wasted
  newSessionAttempts: 1,             // Solved on first try
  newSessionCost: 3000,              // 3K tokens used
  totalTime: 22,                     // 22 minutes total
  solved: true,                      // Success!
};

// If we had continued old session:
// Likely: 8-10 more attempts = 35+ minutes, 35K+ tokens
// Clean slate saved: ~13 minutes, ~17K tokens

Key Indicators

Good reset decision:

  • New session solves in 1-2 attempts
  • Fundamentally different approach
  • Lower token cost than continuing would have been

Premature reset:

  • New session has same issues
  • Should have added more context instead
  • No new insights gained

Too late reset:

  • Wasted 6+ attempts before resetting
  • High token costs in failed session
  • Developer frustration accumulated

Common Pitfalls

❌ Pitfall 1: Not Documenting Why Approaches Failed

Problem: Reset without capturing lessons

You: "That didn't work. Let me start over."

[New session]

You: "Implement authentication"

LLM: "Let's try JWT refresh tokens..."

→ Immediately repeats the same failed approach

Solution: Always document constraints in new session

❌ Pitfall 2: Resetting Too Quickly

Problem: Reset after 1 failed attempt

Udemy Bestseller

Learn Prompt Engineering

My O'Reilly book adapted for hands-on learning. Build production-ready prompts with practical exercises.

4.5/5 rating
306,000+ learners
View Course
Attempt 1: Fails due to typo

→ Reset session immediately

[New session]

→ Still fails because the typo was in your code, not LLM's

Solution: Follow 3-attempt threshold

❌ Pitfall 3: Vague Constraints

Problem: Don’t provide specific constraints

You: "Previous approach didn't work. Try something else."

→ LLM doesn't know what to avoid
→ Might repeat the same approach

Solution: Be explicit about constraints

❌ Pitfall 4: Carrying Baggage

Problem: Copy-paste failed code into new session

[New session]

You: "Here's the code that didn't work: [500 lines]
Can you fix it?"

→ Brings negative context into new session
→ Defeats the purpose of clean slate

Solution: Only bring constraints, not failed implementations

❌ Pitfall 5: Not Verifying New Approach

Problem: LLM immediately implements without discussing approach

[New session with constraints]

LLM: "Here's the implementation: [generates 200 lines]"

→ Might be heading down wrong path again
→ No chance to course-correct before implementation

Solution: Ask for approach proposal first

Cost Analysis

Scenario: Continuing Failed Trajectory

Attempts 1-3: Already failed (15 min, 15K tokens)
Attempts 4-6: Likely to fail (15 min, 15K tokens)
Attempts 7-8: Maybe succeeds? (10 min, 10K tokens)

Total: ~40 minutes, ~40K tokens
Success rate: ~30%

Scenario: Clean Slate Recovery

Attempts 1-3: Failed attempts (15 min, 15K tokens)
Documentation: Capture learnings (2 min)
New session: Fresh start (8 min, 5K tokens)

Total: ~25 minutes, ~20K tokens
Success rate: ~80%

Savings

Time saved: 15 minutes (37% reduction)
Token saved: 20K tokens (50% reduction)
Success rate: +50 percentage points

Key insight: Clean slate becomes profitable after attempt 3. The longer you wait, the less you save.

Conclusion

Clean slate recovery is a proven pattern for escaping bad LLM trajectories.

When to use:

  • 3+ failed attempts
  • LLM suggesting variations of same approach
  • Context accumulating error messages
  • Feeling “stuck in a loop”

How to use:

  1. Recognize pattern (3-attempt threshold)
  2. Document what failed and why
  3. Start fresh session
  4. Frame with explicit constraints
  5. Verify new approach before implementing

Benefits:

  • Escapes negative context accumulation
  • Explores fundamentally different solutions
  • Costs less than continuing broken trajectory
  • Higher success rate
  • Preserves learning without baggage

Key principle: You don’t need failed implementations in context—you only need the constraints they revealed.

The result: Faster problem-solving, lower costs, and less frustration.

Related Concepts

References

Topics
ConstraintsContext ManagementContext RotCost OptimizationDebuggingIterative DevelopmentLlm WorkflowsProblem SolvingSession ManagementTrajectory Recovery

More Insights

Cover Image for Thought Leaders

Thought Leaders

People to follow for compound engineering, context engineering, and AI agent development.

James Phoenix
James Phoenix
Cover Image for Systems Thinking & Observability

Systems Thinking & Observability

Software should be treated as a measurable dynamical system, not as a collection of features.

James Phoenix
James Phoenix