What is it
Debug (or debugging) is the systematic process of finding and fixing errors in code. The name comes from “de-bug” = removing bugs.
It includes:
- Reproduce the problem
- Isolate the root cause
- Understand why it happens
- Fix the code
- Verify the solution works
Common pronunciation mistakes
- ❌ “deh-bug” (the first ‘e’ is long like in “see”)
- ❌ “de-boog” (the ‘u’ sounds like the ‘u’ in “cup”)
Variants:
- Debug (verb): “I need to debug this”
- Debugging (noun/gerund): “Debugging is an art”
- Debugger (tool): “Open the debugger”
Debugging Techniques
1. Print Debugging (The most basic)
function calculateTotal(items) {
console.log('Items received:', items); // 👈 Debug
let total = 0;
for (const item of items) {
console.log('Processing item:', item); // 👈 Debug
total += item.price;
console.log('Partial total:', total); // 👈 Debug
}
console.log('Final total:', total); // 👈 Debug
return total;
}
Pros: Quick, works anywhere Cons: Need to clean up after, no pause capability
2. Debugger with Breakpoints (The most powerful)
function calculateTotal(items) {
debugger; // 👈 Code will pause here
let total = 0;
for (const item of items) {
total += item.price; // You can set breakpoint here
}
return total;
}
Pros: Inspect variables live, step through execution Cons: Requires learning the tool
3. Structured Logging (The most professional)
import logger from './logger';
function calculateTotal(items) {
logger.debug('Starting calculation', { itemCount: items.length });
try {
const total = items.reduce((sum, item) => sum + item.price, 0);
logger.info('Calculation completed', { total });
return total;
} catch (error) {
logger.error('Error in calculation', { error, items });
throw error;
}
}
Pros: Persistent, searchable, doesn’t modify behavior Cons: More initial setup
The Debugging Process
┌─────────────────────────────────────────────────────────────┐
│ DEBUGGING CYCLE │
├─────────────────────────────────────────────────────────────┤
│ │
│ 1. REPRODUCE 2. HYPOTHESIZE 3. TEST │
│ ┌───────────┐ ┌───────────┐ ┌───────────┐ │
│ │ Does it │ → │ What could│ → │ Add logs │ │
│ │ always │ │ cause │ │ or │ │
│ │ fail? │ │ this? │ │breakpoints│ │
│ └───────────┘ └───────────┘ └───────────┘ │
│ ↑ ↓ │
│ │ │ │
│ 6. VERIFY 5. FIX 4. ANALYZE │
│ ┌───────────┐ ┌───────────┐ ┌───────────┐ │
│ │ Does fix │ ← │ Modify │ ← │ Was the │ │
│ │ work? │ │ the code │ │ hypothesis│ │
│ │ No │ │ │ │ correct? │ │
│ │ regression│ │ │ │ │ │
│ └───────────┘ └───────────┘ └───────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
Debug Tools by Language
| Language | Tool | Command/Shortcut |
|---|---|---|
| JavaScript | Chrome DevTools | F12 → Sources |
| Python | pdb / debugpy | breakpoint() (Python 3.7+) |
| Java | IntelliJ Debugger | Shift+F9 |
| C# | Visual Studio | F5 |
| Node.js | VS Code Debugger | F5 |
| React | React DevTools | Chrome Extension |
Real-World Example: Debugging a Login
The problem
“Users can’t log in. The form doesn’t do anything when submitted.”
Step 1: Reproduce
// Try to login and observe in console
form.addEventListener('submit', handleLogin);
Step 2: Add strategic logs
async function handleLogin(event) {
console.log('1. Submit event fired'); // Does it execute?
event.preventDefault();
console.log('2. preventDefault executed');
const email = document.getElementById('email').value;
const password = document.getElementById('password').value;
console.log('3. Data:', { email, password: '***' });
try {
console.log('4. Sending request...');
// The frontend runs on http://localhost:5173 and the API on another origin
const response = await fetch('http://localhost:3000/api/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ email, password })
});
console.log('5. Response:', response.status);
const data = await response.json();
console.log('6. Data:', data);
} catch (error) {
console.error('7. Error:', error); // 🐛 Here it is!
}
}
Step 3: Find the bug
Console:
1. Submit event fired
2. preventDefault executed
3. Data: { email: "user@test.com", password: "***" }
4. Sending request...
7. Error: TypeError: Failed to fetch // 🐛 FOUND IT!
Step 4: Investigate further
// "Failed to fetch" points to a network or CORS problem.
// DevTools → Console/Network shows:
// "blocked by CORS policy: No 'Access-Control-Allow-Origin' header"
// The browser blocks the response because the backend (another origin)
// doesn't allow the frontend's origin.
Step 5: Fix
// backend/server.js (Express) - allow the frontend's origin
import cors from 'cors';
app.use(cors({ origin: 'http://localhost:5173' })); // 🔧 The fix lives in the backend
// Development alternative: a dev-server proxy (e.g. Vite)
// so frontend and API share the same origin.
Advanced Techniques
Rubber Duck Debugging
Explain the problem to an object (like a rubber duck). By verbalizing the problem, you often find the solution.
Binary Search Debugging
If you have a bug in 1000 lines of code:
- Comment out half (lines 500-1000)
- Does the bug persist? → It’s in lines 1-500
- Comment out half of that range
- Repeat until you find the exact line
With Git, git bisect applies the same idea to history: it finds the commit that introduced the bug.
Time-Travel Debugging
Some tools allow you to “go back in time”:
- Redux DevTools (JavaScript)
- rr (C/C++)
- WinDbg Time Travel Debugging (Windows)
Debugging Anti-patterns
| Anti-pattern | Problem | Best practice |
|---|---|---|
| Random changes | “Let me try this and see if it works” | Form a hypothesis first |
| Ignoring stack trace | Googling without reading the error | Read the complete message |
| Not reproducing first | Assuming you know the problem | Always reproduce first |
| Debugging in production | Modifying live code | Use staging/local |
| Not writing tests | The bug comes back later | Add failing test before the fix |
The Debugger’s Mantra
"Don't guess. Observe."
"If you can't reproduce it, you can't fix it."
"The code does exactly what you told it, not what you wanted."
Related terms
- Bug - The error we’re looking for
- Breakpoint - Point where we pause execution
- Stack Trace - Trail of calls leading to the error
- Logging - Event recording for analysis
Remember: Debugging is a skill that improves with practice. The best debuggers aren’t those who know the most, but those who ask and observe the best.