SyntaxError: '(' was never closed
1 · The lesson
readWhat this error means
You opened a bracket — (, [ or { — and Python never found the one that closes it. The message names the bracket type, so you will also see '[' was never closed and '{' was never closed. The arrow points at the opening bracket that has no partner, which makes this one of the friendlier syntax errors: the line it names is usually the line to fix.
In Python 3.9 and earlier the same mistake produced a much less helpful message, SyntaxError: unexpected EOF while parsing ("EOF" is end of file), or a bare invalid syntax on the line after the real problem. If an older tutorial shows either of those for a missing bracket, this is the modern version of it.
When you see it
File "main.py", line 2 total = sum(orders ^ SyntaxError: '(' was never closed
File "main.py", line 1 user = {"name": "Linus", "plan": "pro" ^ SyntaxError: '{' was never closed
A close cousin appears when a bracket is closed, but by the wrong kind:
File "main.py", line 2 cheapest = min(prices] ^ SyntaxError: closing parenthesis ']' does not match opening parenthesis '('
Python calls all three bracket types "parenthesis" in these messages. Read it as "you closed a ( with a ]".
Why it happens
Inside brackets, Python lets an expression run over as many lines as it likes. That is a feature — it is how long function calls and dictionaries are written — but it means a missing ) doesn't fail on its own line. Python carries on reading, treats the next lines as part of the same expression, and only complains when that becomes impossible.
The common causes:
- Nested calls where one closer went missing.
print(f"Total: {sum(prices)}"has three openers in a row and it's easy to count two. - A long dictionary or list built over several lines, with the last
}or]deleted while editing. - Mixed-up closers in nested structures:
["tea", "cake"}ormin(prices]. - Copying part of a multi-line call from somewhere else and leaving its tail behind.
When the error line is the wrong line
Python 3.13 is good at pointing to the opener, but in nested structures the reported line can be several lines below the mistake. Here the missing ] belongs on line 3:
customer = {
"name": "Grace",
"orders": [101, 102,
}File "main.py", line 4 } ^ SyntaxError: closing parenthesis '}' does not match opening parenthesis '[' on line 3
The File line says 4, because that is where Python noticed. The message itself says "on line 3", because that is where the unclosed [ lives. Trust the second number.
How to fix it
Go to the bracket the arrow points at and find where its expression should end. Then close it there — not at the end of the line by reflex, because the right place may be in the middle:
orders = [120, 85, 40] total = sum(orders) print(f"Total: {total}")
For nested calls, count from the inside out. Each function call needs its own ):
prices = [3.50, 4.25, 2.00] print("Cheapest:", min(prices)) print(f"Total: {sum(prices):.2f}")
For multi-line structures, put each closer on its own line, lined up with the line that opened it. A missing one then stands out at a glance:
customer = {
"name": "Grace",
"orders": [101, 102],
"address": {
"city": "Leeds",
"postcode": "LS1 4AP",
},
}
print(customer["address"]["city"], len(customer["orders"]))The trailing commas are deliberate. They let you add or reorder lines without touching the line above, which is where a lot of bracket slips start.
Let the editor help. Every mainstream editor highlights the matching bracket when the cursor sits next to one — click on the opener from the error and see where its partner is, or whether it has one. VS Code also colours bracket pairs by depth, so a closer in the wrong colour is a closer in the wrong place.
If you are on Python 3.9 or older and see unexpected EOF while parsing, look for the last bracket you opened in the file. Upgrading gets you the clearer message on this page.
When you'd actually see this in real code
- Wrapping an existing expression in
round(...)orint(...)and adding the opener without the closer. - Building a JSON payload for an API call as a nested dict, and losing one
}in a twenty-line literal. - Writing a long
print(f"...")with function calls inside the braces. - Merging two branches where each side edited a different line of the same multi-line function call.
Related errors
- SyntaxError: invalid syntax — what older Pythons said for many of the same mistakes.
- SyntaxError: unterminated string literal — the same mistake with a quote instead of a bracket.
- IndentationError: unexpected indent — what you get when you split a line without brackets.
See Also
- All Python errors — the full index, by type and by when it happens.
- Dictionaries (tutorial)
- Functions (tutorial)
- f-strings
Found this useful? Share it with a friend who’s learning Python.