The first time a program stops with a wall of red text, it feels like the computer is telling you that you got it wrong. It isn't. An error message is the most useful thing a computer ever says to a beginner: it's a report, written by people who expected you to make exactly this mistake, saying what went wrong and where.
The trouble is that nobody teaches you how to read one. This guide does, with one method that works in Python, JavaScript, Java and SQL. Every error in it is real output, copied from running the code.
The method in one sentence
Every error message answers three questions, and you read it in this order:
- What went wrong? The type of error and its message.
- Where did it happen? The file, the line and sometimes the exact spot.
- Why, or more precisely: which value was not what the program expected?
Most beginners start with question 3, guessing at the cause. Answer 1 and 2 first, and 3 usually answers itself.
Step 1: Find the line that says what went wrong
Error output can be long, but only one line tells you what happened. Where that line is depends on the language.
Python: the last line
Here's a function that works out an average, called with an empty list:
def average(scores):
return sum(scores) / len(scores)
results = []
print(average(results))Traceback (most recent call last):
File "main.py", line 5, in <module>
print(average(results))
~~~~~~~^^^^^^^^^
File "main.py", line 2, in average
return sum(scores) / len(scores)
~~~~~~~~~~~~^~~~~~~~~~~~~
ZeroDivisionError: division by zeroIn Python, the line that matters is at the bottom: ZeroDivisionError: division by zero. Everything above it is the route the program took to get there. Start reading from the bottom.
Java: the first line
Java puts it the other way round. Here's a loop that goes one step too far:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3
at Main.main(Main.java:6)The first line says what happened: the program asked for position 3 in an array of length 3. (Positions start at 0, so the last one is 2.) The at lines below it are the route.
When Java's compiler finds a mistake, before the program even runs, the important line is the one with error: in it:
Compile.java:3: error: ';' expected
int score = 72
^
1 errorJavaScript: the first line in the console
In a browser, errors appear in the developer tools (F12), in the Console tab:
Uncaught TypeError: Cannot read properties of undefined (reading 'length')
at average (script.js:2:17)
at script.js:6:13As in Java, the first line says what happened, and the at lines below it are the route.
SQL: usually one line
Databases are short and to the point:
near "FORM": syntax errorERROR: syntax error at or near "FORM"Both point at the word they couldn't understand: FORM, which should have been FROM.
The type tells you the kind of problem
The first word of that line, the type of error, already narrows things down a lot. The names differ between languages, but the same few kinds come up again and again:
- A syntax error (
SyntaxErrorin Python and JavaScript,error: ';' expectedin Java,syntax errorin SQL): the code breaks the grammar of the language. A missing bracket, colon, quote or semicolon, or a misspelled keyword. Python's indentation errors belong here too: see IndentationError: expected an indented block. - An unknown name (
NameErrorin Python,ReferenceErrorin JavaScript,cannot find symbolin Java,no such columnin SQLite): you used a name the language doesn't know. Almost always a typo, or something used before it was created. In SQL it's often a missing pair of quotes: see SQL error "no such column" in SQLite. - The wrong kind of value (
TypeErrorin Python and JavaScript,incompatible typesin Java): you mixed things that don't go together, like text and a number. See Python TypeError: 'int' and 'str' and Java: incompatible types: String cannot be converted to int. - A position that doesn't exist (
IndexErrorin Python,ArrayIndexOutOfBoundsExceptionin Java): you asked for item number 3 of a list that only goes up to 2. - No value where one was expected (
NullPointerExceptionin Java,Cannot read properties of nullorof undefinedin JavaScript): a variable that should hold an object holds nothing. See Java NullPointerException and Cannot read properties of null (reading 'addEventListener').
Step 2: Find where it happened
Line numbers and markers
Every error gives a line number, and the line itself is often printed right below it:
- Python marks the exact spot with
^and~under the line. In the average example, the^sits under the/: the division is what failed. - JavaScript gives two numbers after the file name:
script.js:2:17means line 2, column 17 (the 17th character on the line). In the browser, it's a link that opens the file at that spot. - Java's compiler prints the line with a
^under the spot. Theatlines of a runtime error end in the file and line:(Main.java:6). - PostgreSQL also reports the position of the word it stopped at, and tools like
psqlshow it as a marker under your query.
The route: which line is yours?
When the error happens inside a function, the output lists every step of the route: the function that failed, the line that called it, the line that called that one, and so on. This list is called the stack trace or traceback.
The direction is the part that confuses people:
- Python says
most recent call last: the place where it broke is the last entry, just above the error line. In the average example, that's line 2, insideaverage. The entry above it, line 5, is whereaveragewas called from. - Java and JavaScript list the most recent step first: the top
atline is where it broke, and each line below it is one step further back.
In bigger programs the route also passes through code you didn't write: libraries and the language's own files. Skip those and look for the first entry with your file name. That's where you can do something about it.
Syntax errors point at, or just after, the mistake
With a syntax error, the language reports the place where it noticed something was wrong, which can be after the actual mistake. Forget a closing bracket in Python:
name = input("Your name? "
print("Hi", name) File "main.py", line 1
name = input("Your name? "
^
SyntaxError: '(' was never closedModern Python is helpful here: it points at the bracket that was opened and never closed. Java's ';' expected from earlier puts its ^ at the end of line 3, exactly where the missing semicolon belongs. But if a message seems to point at a perfectly good line, always look at the line above it too.
Step 3: Find which value caused it
Now you know what happened and where. The last question is which value on that line was not what you expected, and very often the message says so.
NameError: name 'scroe' is not defined. Did you mean: 'score'?In Python 3.10 and newer, the message even suggests the name you probably meant.Cannot read properties of undefined (reading 'length'): something wasundefinedwhen the code tried to read itslength. On line 2, that'sscores, so the question becomes: why was the listundefinedwhen it was passed in?Index 3 out of bounds for length 3: the program asked for position 3 when the last one was 2. Look at the loop:i <= scores.lengthshould bei < scores.length.ZeroDivisionError: division by zeroonsum(scores) / len(scores):len(scores)was 0, so the list was empty.
When the message doesn't name the value, print it. One extra line just before the line that fails shows you what the program actually had:
print("scores is:", scores)In JavaScript that's console.log("scores is:", scores);, and in Java System.out.println("scores is: " + Arrays.toString(scores)); for an array (with import java.util.Arrays; at the top of the file). Then ask yourself two things: what did I expect this value to be, and where should it have got that value? The bug is usually there, a few lines earlier, and not on the line in the error.
Turn the message into a question about your code
A good habit for step 3 is to rewrite the message as a question about your program. The message describes what the language saw; the question tells you where to look:
TypeError: unsupported operand type(s) for -: 'int' and 'str'becomes: which value on this line is text when I expected a number? (Usually something that came frominput().)incompatible types: String cannot be converted to intbecomes: where does this value come from, and what type does that give? (nextLine()always gives aString.)Cannot invoke "String.length()" because "name" is nullbecomes: where shouldnamehave been given a value, and why wasn't it?Cannot read properties of null (reading 'addEventListener')becomes: why didn'tquerySelectorfind the element? (A typo in the selector, or a script that runs before the HTML exists.)no such column: Vaultbecomes: isVaultmeant to be a column or a value? (A value, so it needs single quotes.)
Each of these has its own article with every cause and fix, linked in the list of error types above.
Fix the first error first
Sometimes you get several errors at once, and sometimes fixing one makes a new one appear. Both are normal. Here's a Java program with two mistakes, a missing semicolon on line 3 and a misspelled scroe on line 4:
public class Compile {
public static void main(String[] args) {
int score = 72
System.out.println(scroe);
}
}The compiler only reports the first:
Compile.java:3: error: ';' expected
int score = 72
^
1 errorAdd the semicolon, compile again, and now it finds the second:
Compile.java:4: error: cannot find symbol
System.out.println(scroe);
^
symbol: variable scroe
location: class Compile
1 errorSo fix the first error, then run again. One mistake can confuse the language about everything after it, and later errors in a long list are often just consequences of the first. A new error after a fix isn't a step backwards; it usually means the program got further than before.
When the message seems to make no sense
Sometimes the message seems unrelated to your code. Three habits help:
- Read it literally. In Java,
Cannot invoke "java.lang.Integer.intValue()"appears even though you never wroteintValue(): Java calls it for you when it turns anIntegerinto anint. In PostgreSQL,column "ana" does not existappears when you wroteAnawithout quotes: it readsAnaas a column name, and lower-cases it. Strange messages almost always describe exactly what the language tried to do. - Search for the generic part. Copy the message without your own names and add the language: "Python ZeroDivisionError division by zero" finds explanations; "average results line 5" doesn't.
- Explain it out loud, or in writing. Saying "on line 2, scores was empty, so..." often reveals the answer before you finish the sentence.
When there is no error message at all
The hardest bugs are the ones without a message: the program runs, but the result is wrong. A few common ones from our other articles:
- CSS that doesn't apply: the browser skips what it doesn't understand, silently. Instead of reading a message, right-click the element, choose Inspect, and look at which styles are crossed out and why. See CSS not working? 7 reasons your styles don't apply.
- A
GROUP BYthat's missing: SQLite gives a confident but meaningless answer. See SQL GROUP BY errors. - A line that's indented wrong in Python: it runs at the wrong time, with no complaint.
- A sum of decimals that's slightly off:
0.1 + 0.2gives0.30000000000000004, and0.1 + 0.2 == 0.3isFalse. See Why does 0.1 + 0.2 not equal 0.3 in Python?
For these, the method is the same, just without the message to start from: find the first place where the output differs from what you expected, then print the values just before it.
Cheat sheet: where to look in each language
- Python: the what is the last line of the traceback; the where is the
File "...", line Njust above it. - Java: the what comes after
error:(from the compiler) or afterException in thread "main"(while running); the where isFile.java:N, or the firstat ...line that names your own code. - JavaScript: the what is the red line in the browser's Console (F12); the where is the file and line link next to it.
- SQL: the what is the message itself, especially the name it mentions; the where is the word or clause it names.
A checklist for any error
- Find the line that says what happened: the last line in Python, the first in Java and JavaScript, and the line with
error:from the Java compiler. - Read the type: syntax, unknown name, wrong kind of value, missing position, missing value.
- Find where: the line number, the marker, and the first entry in the route that's in your own file.
- For a syntax error, look at the line above too.
- Find which value was wrong: the message often names it; if not, print it.
- Fix the first error, and run again.
Still choosing which language to start with? Which programming language should you learn first? compares the four used here.
