Reading Errors & Debugging
Every programmer, from a school student to a senior engineer, sees error messages every single day. An error message is not the computer telling you off. It is a clue, often a very precise one, about what went wrong and where. Learning to read these clues calmly is one of the most valuable skills in programming.
In this lesson you will learn the three kinds of errors, read Python and JavaScript error messages step by step, and practise a simple method for finding bugs that do not produce any message at all.
Three kinds of errors
| Kind | When it shows up | Example | Does the program run? |
|---|---|---|---|
| Syntax error | Before running, while the code is checked | A missing bracket or colon | No, not even line 1 |
| Runtime error | While running, at the line that fails | Dividing by zero, an unknown name | Yes, until that line |
| Logic error | Never reported | Wrong formula, conditions in the wrong order | Yes, but the answer is wrong |
Syntax and runtime errors at least tell you something is wrong. Logic errors are the sneaky ones: the program runs happily and prints a wrong answer. You catch them only by testing.
Reading a Python traceback
Here is a shop bill program with a bug. The quantity was typed in quotes, so it is a string:
prices = [120, 80, 45]
quantity = "2"
total = 0
for price in prices:
total += price * quantity
print("Total:", total)Running it as a file named bill.py in a terminal shows a traceback, Python's error report:
Traceback (most recent call last):
File "bill.py", line 5, in <module>
total += price * quantity
TypeError: unsupported operand type(s) for +=: 'int' and 'str'Read a traceback from the bottom up:
- The last line is the most important.
TypeErroris the kind of error, and the message says you tried to add (+=) a string (str) to a whole number (int). - The line above shows the code that failed:
total += price * quantity. - The
Fileline says where: line 5 ofbill.py. (In a terminal you see the full path to your file. In the browser editor the file is called<exec>.)
Now think. Why is there a string? price * quantity is 120 * "2", and multiplying a string by a number repeats it, giving "22222...". The fix is to store the quantity as a number: quantity = 2. The error appeared on line 5, but the real mistake was on line 2. This is very common: the error shows where the program noticed the problem, not always where you made it.
Error types you will meet often
| Python | JavaScript | Usual cause |
|---|---|---|
SyntaxError | SyntaxError | A missing bracket, quote, colon or comma |
IndentationError | (none) | Python block lines not lined up |
NameError | ReferenceError | A name used before it was created, or misspelt |
TypeError | TypeError | Wrong type: adding text to a number, calling something that is not a function |
ValueError | (none; often NaN instead) | Right type, bad value, such as int("ten") |
IndexError | (none; gives undefined) | Index past the end of a list |
ZeroDivisionError | (none; gives Infinity) | Dividing by zero |
Notice how often JavaScript gives a strange value instead of an error. That makes JavaScript bugs show up later and further away from their cause, so check your values carefully.
Reading a JavaScript error
JavaScript errors appear in the browser console (press F12) or in the Try-it output, usually in red:
const toppers = ["Meera", "Kabir"];
console.log(toppers[0].toUpperCase());
console.log(toppers[2].toUpperCase());The first line works and prints MEERA. The second fails. In Chrome and Edge the message is:
Uncaught TypeError: Cannot read properties of undefined (reading 'toUpperCase')"Uncaught" means no code was set up to handle the error, so the program stopped. Read the rest as: "you tried to use toUpperCase on something that is undefined". There is no toppers[2] (the array has indexes 0 and 1), so it is undefined. Other browsers word the message differently, but the error type and the idea are the same. In the browser console, the message also shows the file and line number, which you can click.
Finding logic errors with print
When there is no error message, make the program tell you what it is doing. Add temporary print() or console.log() lines that show the values at each step. This program should print an average of 80:
marks = [80, 90, 70]
total = 0
for mark in marks:
total = mark
print("DEBUG mark =", mark, "total =", total)
average = total / len(marks)
print("Average:", average)DEBUG mark = 80 total = 80 DEBUG mark = 90 total = 90 DEBUG mark = 70 total = 70 Average: 23.333333333333332
The debug lines show that total never grows: it just copies each mark. The bug is total = mark, which should be total += mark. Fix it, run again to see Average: 80.0, then delete the debug lines.
A debugging checklist
When something goes wrong, work through these steps instead of changing code at random:
- Read the whole error message, especially the last line, and go to the line number it gives.
- Check the line just above too; a missing bracket on line 4 is often reported on line 5.
- Print the values just before the failing line. Are they the type and size you expected?
- Make the problem smaller. Copy the failing part into a new file with fixed test values.
- Change one thing at a time, and run after each change.
- Explain the code out loud, line by line, to a friend or even a toy. This "rubber duck" trick works surprisingly often, because explaining forces you to notice what the code really says.
- Search the exact error message online, without your own variable names.
When you are ready for a stronger tool, a debugger lets you pause a program at a chosen line, called a breakpoint, and look at every variable. VS Code has one built in (click to the left of a line number to set a breakpoint, then press F5), and so do the browser DevTools. See Debugging with DevTools for JavaScript.
Advanced: handling errors you expect
Some errors are not bugs but bad input, such as a user typing "eighty" for marks. You can catch an error and handle it instead of letting the program stop. Python uses try and except:
entries = ["88", "eighty", "92"]
for text in entries:
try:
marks = int(text)
print("Saved:", marks)
except ValueError:
print(f"Skipped '{text}': not a whole number")Saved: 88 Skipped 'eighty': not a whole number Saved: 92
JavaScript uses try and catch. Because Number("eighty") gives NaN instead of an error, the function below throws its own error when the value is not a number:
function parseMarks(text) {
const value = Number(text);
if (Number.isNaN(value)) {
throw new Error(`"${text}" is not a number`);
}
return value;
}
for (const text of ["88", "eighty", "92"]) {
try {
console.log("Saved:", parseMarks(text));
} catch (error) {
console.log("Skipped:", error.message);
}
}Saved: 88 Skipped: "eighty" is not a number Saved: 92
Catch only the errors you expect and know how to handle. Hiding every error makes real bugs much harder to find. You will learn more in Errors & Exceptions.
Common mistakes
- Reading only the first line of a traceback. The useful part is at the bottom.
- Changing many things at once. If it starts working, you will not know which change fixed it, and you may have added new bugs.
- Assuming the bug is on the reported line. The cause is often a few lines earlier, where a value was created.
- Forgetting to remove debug prints. Delete them, or the user will see
DEBUGlines.
Key points
- Syntax errors stop the program before it starts; runtime errors stop it at the failing line; logic errors give wrong answers silently.
- Read a Python traceback from the bottom: error type and message first, then the code line and its line number.
- JavaScript often gives
undefined,NaNorInfinityinstead of an error, so bugs appear later. - Use temporary print statements to see values and find logic errors.
- Follow a checklist: read, print values, make it smaller, change one thing at a time.
- Handle expected bad input with
try/except(Python) ortry/catch(JavaScript).
Exercise
This program should print the total marks and the percentage out of 300, but it has three bugs: one syntax error, one runtime error and one logic error. Find and fix all three, one at a time, running after each fix.
marks = [72, 85, 64]
total = 0
for m in marks
total += m
percentage = total / 300 * 10
print("Total:", totl)
print("Percentage:", percentage)Show solution
marks = [72, 85, 64]
total = 0
for m in marks:
total += m
percentage = total / 300 * 100
print("Total:", total)
print("Percentage:", percentage)Total: 221 Percentage: 73.66666666666667
The syntax error is the missing colon after for m in marks. The runtime error is the misspelt totl (a NameError). The logic error is * 10 instead of * 100, which gave a percentage of about 7.4 without any error message.
Quick Quiz
1. Which kind of error lets the program run but gives a wrong answer?
Logic errors produce no message, which is why testing with known answers matters.
2. Where should you start reading a Python traceback?
The last line says what went wrong; the lines above say where.
3. TypeError: Cannot read properties of undefined (reading 'length') means...
Something you expected to be a value (often a missing array item or property) was undefined.
4. What is a good way to find a logic error?
Showing intermediate values reveals the exact step where the program goes wrong.
Learn Intro to Programming with a mentor
Free lessons get you started. Our Python Programming training adds real projects and code reviews from working developers.
- Project-based learning
- Mentor code reviews
- Free counselling call
