DEV Community

Hopkins Jesse
Hopkins Jesse

Posted on

The Secret AI Debugging Workflow Nobody Uses (But Should)

I spent three hours last Tuesday chasing a race condition in a Next.js 15 app.

The error was intermittent. It only happened when I refreshed the page exactly 4 seconds after login.

My usual workflow involves console logging, guessing, and praying. It failed me again.

Then I remembered a feature buried in the VS Code settings that most developers ignore.

It is not about generating code. It is about understanding execution flow.

This is the "Trace-First" debugging workflow.

Most devs use AI to write boilerplate. I started using it to map state changes.

The results were shocking. My debug time dropped from hours to minutes.

Here is exactly how I set it up, why it works, and where I messed up initially.

The Problem with Standard AI Debugging

We all know the drill.

You paste an error message into Cursor or Copilot Chat.

The AI suggests a fix. You apply it. The error persists.

You paste the new error. The AI suggests another fix.

This loop is expensive. It wastes tokens and, more importantly, mental energy.

In 2026, LLMs are great at syntax. They are still mediocre at context.

They do not know what your useEffect did three renders ago.

They do not see the network request that failed silently in the background.

I realized I was asking the wrong question.

Instead of asking "How do I fix this?", I needed to ask "What actually happened?"

I needed a timeline. A forensic audit of my application state.

Manual logging is too slow. Setting breakpoints is too disruptive for async flows.

I needed a way to dump structured execution data that an AI could actually read.

The Trace-First Setup

The core idea is simple.

Create a middleware or wrapper that logs every significant event to a structured JSON file.

Then, feed that JSON file to your AI assistant.

Do not paste screenshots. Do not paste vague descriptions.

Paste the raw data trace.

I built a lightweight tracer for my React Server Components.

It hooks into the fetch calls and state updates.

Here is the basic structure I used. It is not pretty, but it works.

// lib/tracer.ts
import fs from 'fs';
import path from 'path';

const TRACE_FILE = path.join(process.cwd(), '.trace', 'debug-log.json');

export function logTrace(event: string, data: any, metadata?: any) {
  const entry = {
    timestamp: new Date().toISOString(),
    eventId: crypto.randomUUID(),
    event,
    data,
    metadata: metadata || {}
  };

  // Append to file safely
  try {
    if (!fs.existsSync(path.dirname(TRACE_FILE))) {
      fs.mkdirSync(path.dirname(TRACE_FILE), { recursive: true });
    }

    const existing = fs.existsSync(TRACE_FILE) 
      ? JSON.parse(fs.readFileSync(TRACE_FILE, 'utf-8')) 
      : [];

    existing.push(entry);
    fs.writeFileSync(TRACE_FILE, JSON.stringify(existing, null, 2));
  } catch (e) {
    console.error('Trace write failed', e);
  }
}
Enter fullscreen mode Exit fullscreen mode

I wrapped my API calls with this function.

Every time a fetch started or finished, it logged the payload and the response status.

When a component re-rendered, I logged the props it received.

This created a chronological history of the bug.

The Workflow in Action

Last week, I had a bug where user preferences were not saving.

The UI showed the update. The database remained unchanged.

Old me would have checked the API route. Then the Prisma schema. Then the network tab.

New me ran the app, reproduced the bug, and stopped.

I opened the .trace/debug-log.json file.

It had 42 entries. Too many for a human to scan quickly.

Perfect for an LLM.

I opened Copilot Chat and typed:

"Analyze this trace log. Find where the state diverges from the expected database write. Look for missing fields or silent failures."

I pasted the JSON.

The AI responded in 8 seconds.

It pointed out entry #38.

The frontend sent a PATCH request with theme: 'dark'.

The backend received it. But entry #39 showed the validation layer stripping the theme field because it was not in the allowed enum list.

The enum had been updated in the database but not in the Zod schema.

The error was silent. The API returned 200 OK with the original data.

Without the trace, I would never have seen that the payload was modified mid-flight.

With the trace, the AI spotted the schema mismatch instantly.

I fixed the Zod schema. The bug vanished.

Total time: 12 minutes.

Previous average time for this type of bug: 2.5 hours.

Why This Beats Breakpoints

Breakpoints pause time. They are static.

Async bugs are dynamic. They happen across time and threads.

A breakpoint tells you the state now.

A trace tells you the state then, before, and after.

AI models excel at pattern matching in text.

JSON is text. It is structured, predictable text.

When you give an AI a trace, you are giving it the full context window.

You are removing the guesswork.

I tested this on five different bugs over two weeks.

Here is the breakdown:

Bug Type

💡 Further Reading: I experiment with AI automation and open-source tools. Find more guides at Pi Stack.

Top comments (0)