Definition
A Python script sometimes refuses to start without a single one of its lines getting the slightest chance to run. The screen shows an error message, but nothing happened before it: no output, no calculation, not even the start of a computation. You are looking at a SyntaxError.
SyntaxError reports a file Python cannot read. It belongs to a family of its own, the only one Python catches before it starts executing anything at all. This particularity changes how you deal with it: it is not an exception like the others, and a try wrapped around the code is useless against it, since the block itself is never reached.
Here is what the most common message looks like, a missing colon at the end of a line.
if age > 18
print("Adult")
# SyntaxError: expected ':'The causes, by frequency
A small handful of mistakes keep coming back from one project to the next. Knowing them in advance means recognising the error at a glance instead of rereading the whole file line by line.
| What is missing or off | Where to look |
|---|---|
| Missing colon | End of an if, for or def line |
| Unclosed bracket or quote | The reported line, but mostly the one before |
| Single equals instead of double | Inside a condition |
| Reserved word used as a name | class, import, in as a variable |
| Language version | Recent syntax on an older Python |
Read the line number with suspicion
The natural reflex, faced with an error message, is to jump straight to the line it names. With a SyntaxError, that reflex sometimes misleads: Python reports where it realised something was wrong, which is not always where the fault actually sits. A bracket forgotten at the end of line 10 very often produces an error announced on line 11, because the reader carried on, assuming the expression continued, and only stumbled once it went further.
The move that saves the most time is therefore to check the line before the one reported, not only that line itself. Since version 3.10 the messages are far more precise and often name what is missing, like the expected ':' in the example above: worth leaning on before going looking further down.
Telling it apart from its neighbours
Two close errors derive directly from it, close enough that they sometimes get confused with it. IndentationError and TabError are special cases of SyntaxError: the file is syntactically fine everywhere except for indentation, misaligned in one case, mixing spaces and tabs in the other. All three produce the same effect, nothing starts, and are fixed the same way, by rereading the file rather than looking for an explanation on the execution side.
Conversely, a NameError or a TypeError happen during execution, on code that is perfectly readable to Python. A simple test settles which family you are dealing with: if a program printed anything at all before stopping, the reading succeeded, and it is never a syntax error.
The case that traps everyone
One particular case deserves to be seen once and for all, since it comes back so often. A bracket opened and never closed raises nothing where it sits, but much further down, sometimes twenty lines later.
total = compute(price, quantity # bracket never closed
message = "Order saved"
# SyntaxError reported on the message line, not on the computationThe message then points at a perfectly correct line, which sends you looking in the wrong place and burns long minutes. Faced with a baffling error, the first thing to check remains the balance of brackets and quotes above it, not the reported line itself.
Python keeps reading, convinced the expression continues, and only gives up once it meets something impossible to interpret. It is this gap between the cause and the report that makes the case so misleading.
Frequently asked questions
Why does nothing run when the error is at the end of the file?
Because Python reads and compiles the whole file before running the first line. A syntax fault on line 200 therefore stops the first 199 from running, unlike a runtime error, which does let everything before it run before it stops.
Can a SyntaxError be caught with try?
Not for its own file, since the try itself never runs when the fault sits in the code surrounding it. It only becomes possible when code is loaded and compiled dynamically at runtime, which stays a rare and specialised use.
How can these errors be avoided day to day?
An editor set up for Python flags them as you type, before the file is even saved. Automatic formatters also refuse to touch an unreadable file, which moves the discovery of the error to writing time rather than to when the program launches.