Skip to content
JavaScript Debugging in Chrome

7 Minutes

JavaScript Debugging in Chrome

Fix Bugs Faster! Log Collection Made Easy

Get started

What is JavaScript debugging in Chrome?

Imagine you’re mechanic trying to fix a car.

There’s this magic piece of kit that allows you to pause the engine and see inside every moving part. You can tweak parts live, test changes instantly and measure which parts are slowing the whole thing down.

This is JavaScript debugging in Chrome.

Using Chrome DevTools, you can pause execution, inspect variables and scope, and follow code as it runs. So you can see what the code is actually doing at runtime, without assumptions.

Today we’re going to dive into the technology: every gear, every lever, every efficiency gain. Here’s a full rundown of what we’ll cover.

How to debug JavaScript in Chrome

Like most aspects of coding, effective debugging is about a repeatable process, not random trial and error.

In real projects, JavaScript debugging in Chrome usually follows this workflow:

  1. Open DevTools and the Sources panel
  2. Reproduce the bug consistently
  3. Pause execution at the right moment
  4. Add targeted breakpoints
  5. Reload correctly
  6. Inspect call stack and runtime values
  7. Step through execution
  8. Verify the fix and prevent regressions

Each step answers a specific JavaScript debugging question:

  • Where does execution stop?
  • Which values are wrong (and when do they change)?
  • What line or condition introduces the bug?

(If you’ve got this far and you’re thinking ‘this is too narrowly focused on Chrome DevTools’ no problem: we’ve got a broader guide on JavaScript debugging).

A real JavaScript bug example

To anchor this run-through, we’ll keep running it back to a small demo app called Greet Me.

What the app does:

  • Takes a name and a short message.
  • Builds a greeting string.
  • Produces an incorrect output containing NaN .

There’s no exception and no Console error.

The app runs, but the result is wrong – a scenario that you may have seen before if you’ve debugged with JavaScript.

We’ll use this as a reference example to explain where each debugging step applies, even when the interaction isn’t shown inline.

Step 1: open Chrome DevTools

To control JavaScript execution, open Chrome DevTools and switch to the Sources panel.

You can open DevTools by:

  • Right-clicking the page → Inspect
  • Using the shortcut
    • macOS: ⌘ + ⌥ + I
    • Windows/Linux: Ctrl + Shift + I
  • Chrome menu ⋮ → More toolsDeveloper tools

Once open:

  • Select the Sources tab
  • Make sure the code editor and debugger panels are visible

For a full overview of the interface, see Chrome DevTools and its panels.

Step 2: reproduce the bug consistently

For effective debugging, the bug must be repeatable.

In this app we:

  • Enter a name and a wish
  • Click Create Greeting
  • The output includes NaN

As we mentioned, in this example the Console error appears and the app keeps running.

As long as the same steps always produce the same wrong result, we’re ready to pause execution and inspect what’s happening.

The Greet Me demo app displaying an incorrect output — "Hello Jack, Your wish NaN may come true!" — caused by a unary plus bug in JavaScript

Step 3: pause JavaScript execution

This bit’s crucial: we must stop execution at exactly the right time.

Pause methodWhen to use it
Automatic pause in Chrome DevToolsStops execution when an error is thrown or a breakpoint is hit. Best when failures happen deep in the call stack or the breaking line isn’t obvious yet.
debugger statementPauses execution exactly at that line in code. Useful for hard-to-reach paths, loops, or dynamic conditions. Works consistently across reloads.
Pause from the JavaScript ConsoleInterrupts execution on demand without editing source files. Ideal for exploratory debugging when the execution path is unclear.

Once execution is paused, inspection works the same regardless of how the pause happened.

If execution pauses unexpectedly or not at all, see JavaScript debugger statement explained.

Step 3a: Set JavaScript breakpoints

Breakpoints are great because they let us stop execution only where it matters.

Breakpoint typeWhen to use it
Line-of-codeWhen a specific block looks suspicious
ConditionalWhen the bug appears only for certain values
Event listenerWhen debugging clicks or user actions
DOMWhen issues are triggered by page updates

For a full walkthrough, see How to set and use JavaScript breakpoints.

Step 4: reload the page correctly

With DevTools open and the breakpoints set:

  1. Reload the page normally (⌘R / Ctrl+R)
  2. Reproduce the bug

If scripts appear stale:

  1. Right-click Reload
  2. Select Empty Cache and Hard Reload

Use hard reloads only when caching interferes with debugging.

Step 5: understand what’s happening in the code

Once execution is paused, the goal is to understand the current runtime state before changing anything. At this stage, Chrome DevTools helps us answer three questions:

  • How did execution get here?
  • What data is the code working with right now?
  • Which assumptions are already broken?
DevTools signalWhat it tells you
Call stackWhich functions were executed and in what order
Scope & thisWhich variables are available and what context the code is running in
Value inspectionWhether variables and expressions hold the expected values
Watch expressionsHow key values change as execution progresses

In many cases, the root cause handily reveals itself at this point.

Chrome DevTools Sources panel paused on a breakpoint at line 16, with the Call Stack panel highlighted showing the execution order: logger, print, and onclick
Chrome DevTools Scope panel displaying local variables: message as undefined, name as "Jack", and wish as "Want to be a King"

Monitor expressions with the Watch panel

The Watch panel gives us a microsocope to track how specific values change while execution is paused.

Instead of repeatedly inspecting the same variables, we can pin expressions and observe their values as execution moves forward. This is especially useful for derived values, conditions, or state that changes across multiple function calls.

To add a watch expression:

  • Click the + icon in the Watch panel
  • Enter any valid JavaScript expression (for example, a variable or computed value)

Once added, the expression updates automatically whenever execution pauses, making it easy to see whether values evolve as expected.

Chrome DevTools Sources panel paused at line 14, with the Watch panel showing wish as "Want to be a King" and inline tooltips displaying the values of name, wish, and message

Watch expressions can also be managed from the Console drawer, which provides quick access while inspecting state.

Using the JavaScript console while paused

While execution is paused at a breakpoint, the Console can be used to:

  • Inspect variable values.
  • Test expressions in the current scope.
  • Call functions without reloading the page.

This is useful for quick checks and validating assumptions without modifying source code.

For deeper console usage patterns and logging techniques, see JavaScript console.log explained

Step 6: step through JavaScript execution

Once execution is paused and the runtime state is understood, we can start moving execution forward in a controlled way.

Stepping lets us follow the exact path JavaScript takes, without guessing or adding logs.

ActionWhen to use it
StepMove line by line and enter function calls
Step overSkip over functions you trust
Step intoInspect a function that may be misbehaving
Step outExit the current function early
ResumeJump to the next breakpoint
Figure 7: Step through controls

These controls help confirm where logic diverges from expectations and why.

If you need a more detailed breakdown of stepping actions, shortcuts, and real examples, see How to step through JavaScript code in Chrome DevTools

Step 7: apply the fix

So we’ve found the root cause.

The unintended unary plus forces JavaScript to coerce wish into a number, producing NaN when the value is not numeric.

Removing that extra + fixes the issue.

// Fix: remove the unintended unary '+'
const message ='Hello '
  + name
  +', Your wish `'
  + wish
  +'` may come true!';

This change ensures the wish value is treated as a string, not coerced into a number.

After applying the fix, the greeting renders correctly and no longer produces NaN.

You can also test the behavior in the fixed version of the app.

Step 8: verify the fix and prevent regressions

After applying the fix, it’s important to confirm that the original issue is resolved and that no new problems were introduced.

At this stage, we should:

  • Re-run the original reproduction steps
  • Confirm the incorrect output (NaN) no longer appears.
  • Remove temporary breakpoints or debugger statements.
  • Consider adding guards or defaults to prevent similar issues.

Note that the debugging process complete once we’ve done the verification stuff.

Final takeaway: a practical JavaScript debugging workflow

JavaScript debugging in Chrome works best when bugs are local, visible, and reproducible.

Following a structured process—pausing execution, inspecting runtime state, stepping through code, and verifying fixes—helps us understand why issues happen instead of guessing.

Chrome DevTools are usually enough.

However, they reach limits when bugs:

  • Only affect real users
  • Can’t be reproduced locally
  • Happen in production-only conditions

In those cases, collecting real runtime data becomes necessary.

Tools like Bugfender complement Chrome DevTools by capturing logs and runtime context from real user sessions, without requiring reproduction.

Use DevTools for what you can see.

Use production logging for what you can’t.

Expect The Unexpected!

Debug Faster With Bugfender

Start for Free
blog author

Aleix Ventayol

Aleix Ventayol is CEO and co-founder of Bugfender, with 20 years' experience building apps and solutions for clients like AVG, Qustodio, Primavera Sound and Levi's. As a former CTO and full-stack developer, Aleix is passionate about building tools that solve the real problems of app development and help teams build better software.

Join thousands of developers
and start fixing bugs faster than ever.