Learning path · Level 4 · Tutorial 9

Trace JavaScript Errors with the Browser Debugger

Investigate a failing local script with console evidence and debugger controls, then verify that the correction addresses the actual cause.

  • Level: Beginner
  • Duration: 20 min
  • 8 steps
Start tutorial Back to the path
Trace JavaScript Errors with the Browser Debugger

What you will go through

  1. Reproduce and Classify the Failure Run a local cart script, record its expected and observed behavior, and classify its initial failure. 3 min
  2. Follow the Error to Its Source Use Console evidence, source links, and stack order to locate the failed helper and its callers. 2 min
  3. Collect Focused Console Evidence Add a safe, targeted Console log to reveal the value reaching the failing cart helper. 2 min
  4. Pause Before or at the Failure 3 min
  5. Inspect Values in the Right Frame Inspect a paused runtime exception in Chrome DevTools, switch to the caller’s frame, and use Scope and Watch evidence to explain an undefined helper argument. 3 min
  6. Trace Execution with Step Controls Use Chrome debugger step controls to enter the cart helper, return to the loop, and observe one iteration's state changes. 3 min
  7. Test an Explanation and Fix the Cause Use paused evidence to make a minimal loop-boundary correction and verify that it prevents the invalid helper call. 2 min
  8. Apply the Debugging Cycle and Recheck Independently diagnose a non-throwing logic error and verify the correction against the original input and relevant edge cases. 4 min

What you will learn

  • Classify a failure as a syntax error, runtime exception, or logic error.
  • Use a console message and stack trace to locate relevant source code.
  • Pause a script and inspect values while stepping through a function or loop.
  • Test a specific explanation for a bug and correct its cause.
  • Recheck the original failing case and a relevant boundary case after the change.

Before you start

  • Process Collections with JavaScript Loops
  • Transform Arrays with Callback Functions
  • Handle Failures with JavaScript Exceptions

Step 1 of 8

Reproduce and Classify the Failure

Run a local cart script, record its expected and observed behavior, and classify its initial failure.

Create the failing example

Set up the local example

Create a folder named debug-cart. In your own editor, create the two files below inside it: index.html and script.js. This is a static local page: no server, project download, or DOM code is needed.

index.html

Save as debug-cart/index.html.

html
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>Debug Cart</title>
  <script src="script.js" defer></script>
</head>
<body>
  <h1>Debug Cart</h1>
</body>
</html>

script.js

Save as debug-cart/script.js. Keep this initial version unchanged while you reproduce the failure.

javascript
const cart = [{ name: 'Notebook', price: 6, quantity: 2 }, { name: 'Pen', price: 2, quantity: 3 }];

function getLineTotal(item) {
  return item.price * item.quantity;
}

function calculateTotal(items) {
  let total = 0;

  for (let index = 0; index <= items.length; index += 1) {
    const item = items[index];
    const lineTotal = getLineTotal(item);
    total += lineTotal;
  }

  return total;
}

function runCart(items) {
  const total = calculateTotal(items);
  console.log('Total:', total);
}

runCart(cart);
Expected output
Uncaught TypeError: Cannot read properties of undefined (reading 'price')
    at getLineTotal (script.js:4:15)
    at calculateTotal (script.js:12:23)
    at runCart (script.js:20:17)
    at script.js:24:1

Chrome wording, indentation, and some stack formatting can vary. The important evidence is the uncaught TypeError and the absence of any final `Total:` line.

Observe the failure in Console

Reproduce before changing code

A useful bug report is reproducible: it records a specific input, the expected result, and the observed result.

Open index.html in Google Chrome. Open Chrome DevTools and select Console. Then refresh the page so the saved script runs again.

For this input, the two cart lines should produce Total: 18. Instead, Console reports an uncaught TypeError, and no final Total: output appears. Record that difference before changing anything.

Expected result versus observed failure

A cart with two items is contrasted with an expected total of 18 and interrupted Console execution marked by a TypeError.

Use the same input each time: expected output is 18, while the initial script stops with a TypeError.

Failure record

Use these three facts as the reproduction record.

A reproducible observation separates what was supplied, expected, and actually seen.
PartRecord
InputThe full two-item cart
Expected resultTotal: 18
Observed resultAn uncaught TypeError; no final Total output

Classify by observed behavior

Three kinds of failure

Classify behavior before trying to fix it:

  • A syntax error means JavaScript cannot parse the source, so the script does not start.
  • A runtime exception happens after a script starts, interrupts its current execution, and can appear as an uncaught error in Console.
  • A logic error lets the script run but produces behavior or a result that is wrong.

An error name is evidence, not a full explanation. Later, you will trace the failing code and test a specific explanation.

Compare the categories

Each category answers a different question about what happened, not why it happened.

Use observed behavior to choose a category.
CategoryWhat you observeShort example
syntax errorScript cannot startA malformed function declaration
runtime exceptionExecution starts, then stopsAn uncaught TypeError in Console
logic errorExecution finishes with a wrong resultA total is computed incorrectly

Check your classification

Classify the evidence

Match each observation to its failure category.

Tap an item and then its matching pair.

Step 2 of 8

Follow the Error to Its Source

Use Console evidence, source links, and stack order to locate the failed helper and its callers.

Read the Console report

Source reference

Keep the initial runtime-error version of script.js open. This reference fixes the line numbers used in this step; do not change it yet.

Initial script.js

The script that produced the Console failure

javascript
const cart = [{ name: 'Notebook', price: 6, quantity: 2 }, { name: 'Pen', price: 2, quantity: 3 }];

function getLineTotal(item) {
  return item.price * item.quantity;
}

function calculateTotal(items) {
  let total = 0;

  for (let index = 0; index <= items.length; index += 1) {
    const item = items[index];
    const lineTotal = getLineTotal(item);
    total += lineTotal;
  }

  return total;
}

function runCart(items) {
  const total = calculateTotal(items);
  console.log('Total:', total);
}

runCart(cart);
Expected output
Uncaught TypeError: Cannot read properties of undefined (reading 'price')
    at getLineTotal (script.js:4:15)
    at calculateTotal (script.js:12:23)
    at runCart (script.js:20:17)
    at script.js:24:1

Chrome wording can vary slightly. The source locations shown here correspond to this displayed file version.

Split the Console report into clues

Read a Console report as three separate clues. TypeError is the error name; it identifies a kind of invalid operation. Cannot read properties of undefined (reading 'price') is the message; it describes the failed operation. script.js:4:15 is the source location; it points to the relevant statement.

Click that source link in Console. Chrome opens Sources at the property read on line 4. This tells you where the exception occurred, not yet why item had that value.

Error names are clues, not complete diagnoses. A SyntaxError prevents parsing, a ReferenceError involves an unavailable binding, and a TypeError means an operation does not fit the current value.

What each Console part contributes

Use all three parts together; the source location is the fastest route from a Console report to code.

A Console error combines a classification, a description, and a place to investigate.
Console partMeaningUseful question
Error nameBroad kind of failureWhat kind of operation failed?
MessageSpecific failed operationWhat value or operation is involved?
Source locationFile, line, and columnWhich statement should I inspect?

From Console to Sources

A schematic Console error report with a source-location link leading to a highlighted property-access statement in Sources.

Treat the location link as a route to the failing statement; use the name and message to decide what to investigate there.

Use the call path as evidence

Read the stack from failure outward

The stack trace records the synchronous call path from the most recent call outward. For this script, read from the top helper entry back through its callers:

  • getLineTotal is where the exception occurs: script.js:4:15.
  • calculateTotal immediately called that helper at script.js:12:23.
  • runCart called calculateTotal at script.js:20:17.
  • The top-level call began at script.js:24:1.

The top stack entry identifies the failed helper. The next entry identifies its immediate caller.

Example

Example runtime stack

Console wording and columns can differ slightly by Chrome version. The important pattern is the ordered function path and the source link beside each entry.

Uncaught TypeError: Cannot read properties of undefined (reading 'price')
at getLineTotal (script.js:4:15)
at calculateTotal (script.js:12:23)
at runCart (script.js:20:17)
at script.js:24:1

Call flow and stack order

A call flow descends from the top-level call to runCart, calculateTotal, and getLineTotal, while the stack lists the same path in reverse with getLineTotal first.

Execution flows inward to getLineTotal; the runtime stack reports the active calls outward, starting with that failing helper.

Tip

Failure site is not automatically the cause

Do not equate the exception line with the original cause. Line 4 is where reading price fails. The caller entry on line 12 shows where getLineTotal(item) was invoked. To investigate how its argument was obtained, inspect the earlier assignment on line 11 as a possible source of the value.

Keep the distinction: failure site versus an earlier operation that may have supplied a bad value.

Practice reading a runtime stack

Locate the failure and its caller

Match each Console or stack-trace fragment to its role.

Tap an item and then its matching pair.

Step 3 of 8

Collect Focused Console Evidence

Add a safe, targeted Console log to reveal the value reaching the failing cart helper.

Choose evidence before editing

Start with a diagnostic question

Before adding any log, choose one question that could separate a guess from evidence:

Does every loop iteration supply an item to getLineTotal?

The loop already has the values needed to answer it. Immediately before the helper call, record:

  • items.length — the array boundary
  • index — the current position
  • typeof item — a safe description of the value being passed

This is focused evidence, not a permanent transcript of every value in the program.

Trace the value passed on each iteration

A loop visits array positions zero, one, and then two; the first two contain objects, while position two is empty before reaching the helper.

The diagnostic log compares the loop index with the array length and safely reports the type of the value about to enter the helper.

Tip

Keep the log safe

Use short labels and primitive values. typeof item is safe even when item is undefined; avoid a log such as item.name, which would create another property-access failure at the very moment you need evidence.

Read the Console sequence

Add one targeted log

In script.js, add one temporary log after const item = items[index]; and before the helper call. In this displayed version, the log is at script.js:12:5 and the helper call is at script.js:13:23.

Save the file, reload the local page in Chrome, and read the entries in the Console from top to bottom. Keep index.html unchanged.

script.js with a temporary diagnostic log

Save this diagnostic version of script.js, then reload the local HTML page.

javascript
const cart = [{ name: 'Notebook', price: 6, quantity: 2 }, { name: 'Pen', price: 2, quantity: 3 }];

function getLineTotal(item) {
  return item.price * item.quantity;
}

function calculateTotal(items) {
  let total = 0;

  for (let index = 0; index <= items.length; index += 1) {
    const item = items[index];
    console.log('Check:', 'length', items.length, 'index', index, 'item type', typeof item);
    const lineTotal = getLineTotal(item);
    total += lineTotal;
  }

  return total;
}

function runCart(items) {
  const total = calculateTotal(items);
  console.log('Total:', total);
}

runCart(cart);
Expected output
Check: length 2 index 0 item type object
Check: length 2 index 1 item type object
Check: length 2 index 2 item type undefined
Uncaught TypeError: Cannot read properties of undefined (reading 'price')
    at getLineTotal (script.js:4:15)
    at calculateTotal (script.js:13:23)
    at runCart (script.js:21:17)
    at script.js:25:1

Chrome may format Console entries slightly differently, but the sequence, values, and absence of the final Total line are the important evidence.

Practice the diagnostic expression

Build a safe diagnostic log

Complete the expression that makes this diagnostic log safe for every loop iteration.

javascript
for (let index = 0; index <= items.length; index += 1) {
  const item = items[index];
  console.log('Check:', 'length', items.length, 'index', index, 'item type', );
  const lineTotal = getLineTotal(item);
  total += lineTotal;
}

Run and report what the log proves

Record the focused evidence

Run the completed diagnostic version in your own local page. Then record the evidence in one short response:

  1. Write the complete labeled console.log line you used.
  2. Name the first loop index that supplied an unexpected value.
  3. State the two observations that support your conclusion.

Do not change the loop condition yet. This screen is about collecting evidence, not applying a correction.

Write at least 80 characters (0/80).

Step 4 of 8

Pause Before or at the Failure

Restore and pause before a suspected statement

Restore the initial failing script

Step 3 used a temporary diagnostic log. Before setting a breakpoint, restore one canonical source state: replace the entire contents of debug-cart/script.js with the version below and save it. This removes the temporary log and restores the line map used in the next steps.

Keep index.html unchanged. The saved script still throws, so it is ready for a controlled investigation.

Canonical initial script.js

Save this as the complete contents of debug-cart/script.js.

javascript
const cart = [{ name: 'Notebook', price: 6, quantity: 2 }, { name: 'Pen', price: 2, quantity: 3 }];

function getLineTotal(item) {
  return item.price * item.quantity;
}

function calculateTotal(items) {
  let total = 0;

  for (let index = 0; index <= items.length; index += 1) {
    const item = items[index];
    const lineTotal = getLineTotal(item);
    total += lineTotal;
  }

  return total;
}

function runCart(items) {
  const total = calculateTotal(items);
  console.log('Total:', total);
}

runCart(cart);
Expected output
Uncaught TypeError: Cannot read properties of undefined (reading 'price')
    at getLineTotal (script.js:4:15)
    at calculateTotal (script.js:12:23)
    at runCart (script.js:20:17)
    at script.js:24:1

Chrome Console wording and stack formatting can vary slightly. The important locations are the property read at `script.js:4:15` and its helper-call entry at `script.js:12:23`.

Set a source breakpoint before the helper call

Use a source breakpoint when you want to stop before a statement in a suspected region. In DevTools, open Sources, select script.js, and click the gutter beside const lineTotal = getLineTotal(item); at script.js:12:23.

A source breakpoint pauses before its selected statement executes. The local page already ran its deferred script when it opened, so reload the page after setting the breakpoint. The statement is highlighted when execution pauses, and getLineTotal(item) has not run yet.

Choose Resume script execution to continue the current run until another pause or until execution finishes.

Recognize a source-breakpoint pause

A Sources panel diagram with a breakpoint marker beside the helper-call line, an execution highlight on that line, and the Resume script execution control.

A source breakpoint stops before the highlighted helper-call statement executes.

Pause at an uncaught exception

Pause directly at the thrown failure

Use Pause on uncaught exceptions when you expect a runtime exception but do not want to select a suspected line first.

For a separate exception investigation, disable the source breakpoint by clicking its gutter marker. In Sources, enable Pause on uncaught exceptions, then reload the local page. DevTools pauses at the throwing property read in getLineTotal: script.js:4:15.

This pause identifies where the exception occurs. It does not by itself establish which earlier operation supplied the invalid value. Use a source breakpoint to inspect a known region; use an uncaught-exception pause to locate a thrown failure whose location is not yet known.

Recognize an uncaught-exception pause

A Sources panel paused on the throwing property-access statement, with Pause on uncaught exceptions enabled and no active source breakpoint.

With no enabled line breakpoint, the exception setting stops at the statement that throws.

Choose by investigation question

Both methods require a reload when the page's script has already run, but they answer different questions.

Two pause mechanisms for the initial cart script
Investigation situationPause mechanismWhere execution stops
The helper call at script.js:12:23 is a suspected regionsource breakpointBefore the selected helper-call statement
An uncaught runtime exception is expected, but its location is unknownPause on uncaught exceptionsAt the throwing statement: script.js:4:15

Match the tool to the question

Select the right pause mechanism

You have two separate investigations: inspect a known helper call at script.js:12:23, then locate an uncaught runtime exception whose location is unknown. Which pairing is appropriate?

Apply both pause methods

Plan the reload-and-pause sequence

Arrange this complete two-pass investigation of the local script in the required order.

  1. Reload the local page so the already-run script can reach the source breakpoint.
  2. In Sources, open script.js and set a source breakpoint at script.js:12:23.
  3. At the highlighted helper-call line, use Resume script execution to continue the current run.
  4. For the unknown-location investigation, disable the source breakpoint and enable Pause on uncaught exceptions.
  5. Reload the local page again to pause where the uncaught runtime exception is thrown.

Step 5 of 8

Inspect Values in the Right Frame

Inspect a paused runtime exception in Chrome DevTools, switch to the caller’s frame, and use Scope and Watch evidence to explain an undefined helper argument.

Read Scope at the exception

Start with the paused helper

With the canonical initial script.js still saved, enable Pause on uncaught exceptions in Sources and reload the local page. Chrome pauses in getLineTotal at the failing property read, script.js:4:15.

The initially selected paused frame is getLineTotal. In Scope, inspect its item parameter. Its value is undefined, so the helper received an invalid argument before it attempted to read item.price.

This establishes what failed in the helper. Next, inspect the caller to learn which loop state supplied that argument.

What the helper frame reveals

A debugger schematic shows the getLineTotal frame selected, its item parameter as undefined in Scope, and calculateTotal below it in Call Stack.

Scope shows bindings for the currently selected paused frame.

Inspect the caller's loop state

Switch to the caller frame

In Call Stack, select calculateTotal, the caller listed below getLineTotal. The script remains paused at the same exception; selecting a frame changes only the inspection context. It does not run code, retry the helper call, or move execution backward.

Now Scope shows the caller's local bindings. At this pause, inspect these values:

  • index is 2.
  • items is an array with length 2.
  • item is undefined.
  • total is 18, accumulated from the first two lines.

The lookup on script.js:11:18, items[index], therefore has no array element to supply. The next statement, getLineTotal(item) at script.js:12:23, passes that undefined value into the helper.

Caller state explains the argument

The calculateTotal frame is selected in Call Stack, and Scope shows index 2, an array of length 2, item undefined, and total 18.

Frame selection exposes the caller's loop state without changing the paused execution point.

Front

Does selecting calculateTotal in Call Stack execute the caller again?

Tap to flip

Use Watch without changing state

Add Watch expressions in the right context

Use Watch for small, side-effect-free expressions that answer a focused question. With the calculateTotal frame selected, add these expressions one at a time in the Watch pane:

  • items.length checks the array boundary.
  • items[index] checks the current array lookup.

At this pause, they show 2 and undefined. These values agree with Scope: the current index is at the boundary, so the lookup cannot provide a cart item.

A Watch expression depends on the selected frame's lexical bindings. If you select getLineTotal, items.length can be unavailable because items is not a binding in that helper. That is a scope-context clue, not evidence of a new program bug. Do not use expressions that change values while investigating.

Build the focused Watch checks

With calculateTotal selected in Call Stack, complete the two Watch expressions.

javascript
items.
items[]

Apply the frame evidence

Connect frame, Watch, and invalid argument

Match each investigation need to the frame, Watch completion, or evidence-based conclusion that satisfies it.

Tap an item and then its matching pair.

Step 6 of 8

Trace Execution with Step Controls

Use Chrome debugger step controls to enter the cart helper, return to the loop, and observe one iteration's state changes.

Begin from the first loop iteration

Restart at a useful pause

Use the original failing version of script.js below. Set a source breakpoint at script.js:11:5, on const item = items[index];, then reload the local page in Chrome.

The first pause is a valid iteration: index is 0. A line breakpoint pauses before its statement runs. Do not try to step backward from the later runtime exception. Reloading starts a fresh trace at the first loop pass.

Original cart script

Current script.js — do not change it in this step.

javascript
const cart = [{ name: 'Notebook', price: 6, quantity: 2 }, { name: 'Pen', price: 2, quantity: 3 }];

function getLineTotal(item) {
  return item.price * item.quantity;
}

function calculateTotal(items) {
  let total = 0;

  for (let index = 0; index <= items.length; index += 1) {
    const item = items[index];
    const lineTotal = getLineTotal(item);
    total += lineTotal;
  }

  return total;
}

function runCart(items) {
  const total = calculateTotal(items);
  console.log('Total:', total);
}

runCart(cart);

Debugger controls at a source breakpoint

A Sources-panel diagram shows execution paused before the item assignment on the first loop iteration, with callouts for Step over, Step into, Step out, and Resume script execution.

The execution highlight marks the statement that will run next. The breakpoint marker remains on that source line.

Follow the calculation, then the loop

Trace one helper call and return

Watch how a controlled trace moves through one valid cart iteration.

Stepping is deliberate and local: follow the helper when its calculation matters, then return to the caller to see loop progress.

Transcript

Step over reaches the helper call. Step into opens getLineTotal. Step out returns to calculateTotal. Step over the accumulation advances the loop.

What each control reveals

With the breakpoint still enabled on line 11, use the controls in this sequence to observe one valid iteration. Source locations refer to the displayed script.js version.

A step command stops at the next relevant statement; Resume script execution does not provide this statement-by-statement trace.
ControlUse it while paused atNext locationEvidence to inspect
Step overscript.js:11:5script.js:12:23item is the Notebook record
Step intoscript.js:12:23getLineTotal at script.js:4:10helper item parameter
Step outhelper return statementscript.js:13:5lineTotal is available to caller
Step overscript.js:13:5script.js:11:5 on next passtotal is 12; index is 1
Resume script executionany paused framenext pause eventcontinues freely, not one statement at a time

Check the control choice

Choose the return control

You are paused inside getLineTotal and want to return to calculateTotal to inspect the accumulation there. Which debugger control is specifically intended for that goal?

Apply the step controls locally

Predict, trace, and compare

Use your local page and the breakpoint at the first loop assignment. Trace the first valid iteration.

Before clicking each control, write your prediction. Then perform the trace and compare it with the Sources highlight:

  1. Name the control you will use to inspect the helper calculation, and predict the function and statement that will be reached.
  2. From the helper, name the control you will use to return to the caller, and predict the caller statement that will be reached.
  3. Advance the caller once more. Predict the next loop pause and report the observed index, lineTotal, and total.

Finish by stating whether your predictions matched the local trace.

Write at least 180 characters (0/180).

Step 7 of 8

Test an Explanation and Fix the Cause

Use paused evidence to make a minimal loop-boundary correction and verify that it prevents the invalid helper call.

Explain the observed failure

Turn evidence into an explanation

You already observed the key facts in the paused calculateTotal frame: index was 2, items.length was 2, and item was undefined.

Turn those facts into a testable explanation: the continuation condition permits an iteration when the index has reached the array boundary. That iteration reads items[2], but a two-item array has valid indexes 0 and 1 only.

Predict the effect before editing:

  • The helper call should occur with indexes 0 and 1 only.
  • No helper call should receive undefined.
  • The uncaught TypeError should disappear.
  • The original cart should log Total: 18.

This is a specific causal explanation, not merely “the loop is broken.”

The array boundary explains the failure

A two-item array has positions 0 and 1. A path that continues to position 2 reaches an out-of-range lookup and passes undefined to a helper.

An index equal to the array length is outside this two-item array.

Make one minimal correction

Corrected script.js

In the canonical initial file, the comparison begins at script.js:10:29; the removable = is specifically at script.js:10:30. Replace the complete contents of your local debug-cart/script.js with this corrected version, save it, then reload index.html in Chrome. Disable any source breakpoint left from the previous trace before this reload.

javascript
const cart = [{ name: 'Notebook', price: 6, quantity: 2 }, { name: 'Pen', price: 2, quantity: 3 }];

function getLineTotal(item) {
  return item.price * item.quantity;
}

function calculateTotal(items) {
  let total = 0;

  for (let index = 0; index < items.length; index += 1) {
    const item = items[index];
    const lineTotal = getLineTotal(item);
    total += lineTotal;
  }

  return total;
}

function runCart(items) {
  const total = calculateTotal(items);
  console.log('Total:', total);
}

runCart(cart);
Expected output
Total: 18

Console may retain entries from earlier reloads. The new run should include this final output and no uncaught TypeError.

Tip

Fix the cause, not the symptom

This is a minimal causal correction: it changes the loop boundary and leaves the cart data, helper calculation, accumulation, and final log intact.

Do not hard-code 18, add a guard that silently skips an invalid item, or catch and hide the exception. Those changes could conceal the symptom while leaving the incorrect continuation condition in place.

Verify the predicted effect

Inspect the corrected execution boundary

Confirm the prediction with the debugger, not only with the absence of an error:

  1. In Sources, open the saved corrected script.js and set a source breakpoint on const lineTotal = getLineTotal(item); at script.js:12:5.
  2. Reload index.html. At the first pause, inspect index in Scope. It is 0.
  3. Choose Resume script execution. The breakpoint is reached again; inspect index, which is now 1.
  4. Choose Resume script execution again. The script completes without a third breakpoint pause. Check Console for Total: 18.
  5. Disable the temporary source breakpoint.

The missing third pause is evidence that execution never calls the helper with index 2.

Before and after the correction

Use both execution evidence and the final output for this input.

The breakpoint checks the call boundary; Console checks the returned result.
CheckInitial failing runCorrected run
Helper-call indexes0, 1, then 20, then 1 only
Argument at boundaryundefined at index 2No helper call at index 2
Console outcomeTypeError; no final TotalTotal: 18
What the loop doesPermits index equal to lengthStops before index equals length

Warning

Avoid a false conclusion

Removing a runtime exception is necessary here, but it is not proof that every calculation is correct. The successful Total: 18 confirms this original input after the boundary fix. The next step uses additional cases to investigate a different, non-throwing logic error.

Apply the boundary rule

Complete the corrected condition

Complete the comparison that keeps each loop iteration within the array boundary.

javascript
for (let index = 0; index  items.length; index += 1) {

Explain why this fix is justified

Justify the causal correction

Write the corrected loop condition. Then explain how the observed index of 2, length of 2, and undefined helper argument support that source change instead of an error-suppressing workaround.

Write at least 120 characters (0/120).

Step 8 of 8

Apply the Debugging Cycle and Recheck

Independently diagnose a non-throwing logic error and verify the correction against the original input and relevant edge cases.

Reproduce the incorrect total

Reproduce a non-throwing failure

Use the same local debug-cart folder. Keep the corrected loop, but replace the helper in script.js with this complete logic-error variation. Save the file, open index.html in Chrome, and open DevTools Console.

This script runs to completion, so there is no runtime exception. Its full-cart result is 13, even though the known total is 18. That mismatch is a logic error: execution succeeds, but the calculation is wrong.

script.js — logic-error version

Replace the contents of script.js, save, then refresh the local page.

javascript
const cart = [
  { name: 'Notebook', price: 6, quantity: 2 },
  { name: 'Pen', price: 2, quantity: 3 }
];

function getLineTotal(item) {
  return item.price + item.quantity;
}

function calculateTotal(items) {
  let total = 0;

  for (let index = 0; index < items.length; index += 1) {
    const item = items[index];
    const lineTotal = getLineTotal(item);
    total += lineTotal;
  }

  return total;
}

function runCart(items) {
  const total = calculateTotal(items);
  console.log('Total:', total);
}

runCart(cart);
runCart([cart[0]]);
runCart([]);
Expected output
Total: 13
Total: 8
Total: 0

The three lines appear in Console in this order after one page refresh.

What the failing calculation does

A diagram showing the notebook values 6 and 2 becoming 8, and the pen values 2 and 3 becoming 5, which combine into 13.

The inputs reach the helper successfully. The intermediate line totals reveal the wrong operation, not a failed loop boundary.

Inspect, then plan the recheck

Inspect evidence with a source breakpoint

Apply the debugging cycle even when no exception is thrown:

  1. Reproduce: full cart expected 18; Console reports 13.
  2. Hypothesis: inspect the helper’s calculation rather than assuming the loop is still wrong.
  3. Inspect: in Sources, set a source breakpoint on the return statement at script.js:7:3, then reload.
  4. In the paused helper frame, use Scope to inspect item. Select the calculateTotal entry in Call Stack to see the caller’s index, item, and total.
  5. Use Step over on the return statement. Back in the caller’s paused frame, inspect the new lineTotal.

The first pause should show the Notebook input with price 6 and quantity 2; after the helper returns, lineTotal is 8. Resume to inspect the Pen iteration if needed. The values are valid—the calculation applied to them is not.

Manual recheck record

After you correct the helper, save script.js, reload the page, and use this compact manual-check table. The empty-cart result is important: it can pass even while a helper calculation is wrong, because the helper is not called for an empty array.

Record what Console prints after the corrected script runs.
CaseExpected totalObserved totalMatch?
Full cart18Write your Console resultYes / No
One-item cart12Write your Console resultYes / No
Empty cart0Write your Console resultYes / No

Make the smallest causal correction

Correct the helper calculation

Complete the minimal causal correction for the helper. Do not change the loop or hard-code a total.

javascript
function getLineTotal(item) {
  return item.price  item.quantity;
}

Apply and verify the full cycle

Finish with clean evidence

After applying your correction locally, disable the temporary source breakpoint and remove any temporary diagnostic console.log calls before the final reload. Then complete the manual checks from the previous screen.

Final debugging report

Submit a compact debugging report after your final reload. Include all of the following:

  • The paused item values and lineTotal evidence that exposed the incorrect calculation.
  • The operator you replaced and the operator you used instead.
  • Expected and Console-observed totals for the full cart, the one-item cart, and the empty cart, stating whether each matches.

Use evidence from your own Console and paused frames.

Write at least 120 characters (0/120).

Summary

Key takeaways

  • A logic error can produce a wrong result without a syntax error or runtime exception.
  • A source breakpoint and paused-frame values test a hypothesis with concrete evidence.
  • A passing empty-cart case alone does not prove that a calculation is correct.
  • A complete recheck records expected and observed results for the original input and boundary cases.

Tutorial complete

Congratulations! You completed: Trace JavaScript Errors with the Browser Debugger

You traced a non-throwing logic error, corrected its actual cause, and verified the result with original and boundary cases.

Download the App now to have access to + 5000 free courses, exercises, certificates and lots of content without paying anything!

  • 100% free online courses from start to finish

    Thousands of online courses in video, ebooks and audiobooks.

  • More than 60 thousand free exercises

    To test your knowledge during online courses

  • Valid free Digital Certificate with QR Code

    Generated directly from your cell phone's photo gallery and sent to your email

Cursa app on the ebook screen, the video course screen and the course exercises screen, plus the course completion certificate