On this page

Tutorial8 min read

How to Debug a Next.js Application in VS Code (Complete Guide)

Next.js has two separate debugging environments: server and client. Here's how to attach VS Code to both simultaneously, debug Server Components, API routes, hydration errors, and middleware with breakpoints that actually work.

nextjsvscodedebuggingreactserver-componentsapi-routes

Two Environments, Two Debuggers

Next.js runs code in two separate places. The server handles Server Components, API routes, and middleware. The browser handles Client Components, state, and events. VS Code can attach to both at the same time.

EnvironmentWhat runs hereHow to debug
ServerServer Components, API routes, middleware, getServerSidePropsVS Code Node.js debugger
ClientClient Components ('use client'), browser events, stateBrowser DevTools + VS Code Chrome debugger

Errors in Server Components show up in the terminal. Errors in Client Components show up in the browser console. Knowing which side the error is on tells you which tool to open.

Step 1: Configure VS Code

Create .vscode/launch.json in your project root:

json
{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Next.js: debug server-side",
      "type": "node-terminal",
      "request": "launch",
      "command": "npm run dev"
    },
    {
      "name": "Next.js: debug client-side",
      "type": "chrome",
      "request": "launch",
      "url": "http://localhost:3000"
    },
    {
      "name": "Next.js: debug full stack",
      "type": "node",
      "request": "launch",
      "program": "${workspaceFolder}/node_modules/.bin/next",
      "args": ["dev"],
      "env": {
        "NODE_OPTIONS": "--inspect"
      },
      "serverReadyAction": {
        "action": "debugWithChrome",
        "killOnServerStop": true,
        "pattern": "started server on .+, url: (https?://.+)",
        "uriFormat": "%s",
        "webRoot": "${workspaceFolder}"
      }
    }
  ]
}

Use "Next.js: debug full stack" to attach to both server and browser at once. Breakpoints in Server Components and Client Components both pause in VS Code.

Step 2: Debug Server Components

Server Components run on Node.js. Errors show up in the terminal where npm run dev is running, not in the browser.

typescript
// app/dashboard/page.tsx
export default async function DashboardPage() {
  const data = await fetchUserData()  // set breakpoint here
  return <Dashboard data={data} />
}

Set a breakpoint on fetchUserData(). VS Code pauses when the page loads and you can inspect data before it hits the component.

Note: Server Components run on every request, so breakpoints fire every page visit. Right-click a breakpoint and add a condition to avoid pausing on every load.

Step 3: Debug Client Components

Client Components run in the browser. With "Next.js: debug full stack" active, breakpoints in 'use client' files still pause in VS Code, not the browser. Source maps handle the translation.

typescript
'use client'

export function SearchBar() {
  const [query, setQuery] = useState('')

  const handleSearch = () => {
    // breakpoint here pauses in VS Code when user clicks search
    fetchResults(query).then(setResults)
  }
}

Tip: If breakpoints in Client Components show as unbound, check that sourceMapPathOverrides in your launch config maps webpack paths to your source directory. The default Next.js config usually works without changes.

Step 4: Debug API Routes

API routes in app/api/ or pages/api/ run on the server. Debug them the same way as Server Components.

typescript
// app/api/users/route.ts
export async function POST(request: Request) {
  const body = await request.json()
  // breakpoint here — inspect body before it goes anywhere
  const user = await createUser(body)
  return Response.json(user)
}

Trigger the route with curl while the debugger is attached:

bash
curl -X POST http://localhost:3000/api/users \
  -H "Content-Type: application/json" \
  -d '{"email": "test@example.com"}'

VS Code pauses, you inspect body, step through createUser, and see what gets returned.

Step 5: Fix Hydration Errors

The most common Next.js error:

Error: Hydration failed because the initial UI does not match what was rendered on the server.

This happens when the server renders one thing and the client renders something different during hydration.

Browser-only API used outside useEffect

typescript
// ❌ window doesn't exist on the server
function Sidebar() {
  return <div>{window.innerWidth > 768 ? 'Desktop' : 'Mobile'}</div>
}
typescript
// ✅ runs only after hydration
'use client'

function Sidebar() {
  const [isMobile, setIsMobile] = useState(false)

  useEffect(() => {
    setIsMobile(window.innerWidth <= 768)
  }, [])

  return <div>{isMobile ? 'Mobile' : 'Desktop'}</div>
}

Date or random value rendered on both sides

typescript
// ❌ different value on server vs client
<p>Generated: {new Date().toLocaleString()}</p>
typescript
// ✅ only renders on the client after mount
'use client'

function Timestamp() {
  const [time, setTime] = useState('')
  useEffect(() => setTime(new Date().toLocaleString()), [])
  return <p>Generated: {time}</p>
}

Step 6: Debug Middleware

Middleware runs at the edge before the request reaches your route. Errors here are silent by default and won't show up in the normal error overlay.

typescript
// middleware.ts
export function middleware(request: NextRequest) {
  const token = request.cookies.get('session')
  console.log('middleware token:', token?.value)

  if (!token) {
    return NextResponse.redirect(new URL('/login', request.url))
  }
}

Note: Middleware runs in the Edge Runtime, not Node.js. VS Code's Node debugger can't attach to it. Use console.log and check the terminal output.

Common Errors Quick Reference

ErrorEnvironmentCause
Hydration failedClientServer and client rendered different output
window is not definedServerBrowser API used in a Server Component
useEffect not availableServerClient hook in Server Component, add 'use client'
404 on dynamic routeServergenerateStaticParams returned empty or dynamicParams = false
Middleware redirect loopEdgeRedirect target matches middleware pattern, add exclusion
CORS on API routeServerMissing Access-Control-Allow-Origin header in response

For Next.js bugs that cross Server Components, Client Components, and API routes — especially when the wrong data arrives at the wrong component — paste the error and component tree into DebugAI. It traces the full chain from server fetch to client render and shows where the data goes wrong.

Debug faster starting today.

Free VS Code extension. 10 sessions/day. No credit card.

Install Free →

Related Posts

Tutorial

How to Debug a FastAPI Application (Complete VS Code Guide)

9 min read

Tutorial

Fix KeyError in Python: 5 Causes and How to Find the Source

5 min read

← All posts