"IndentationError: unexpected indent" means Python found a line that is indented further than it should be, when nothing above it (no line ending in a colon, like if, for or def) opened a new block. To fix it, line the reported statement up with the code around it, usually by deleting the extra spaces at the start of that line. If the error says TabError or "unindent does not match any outer indentation level", the real problem is mixed tabs and spaces or a dedent to a column that never existed.
Python uses indentation instead of curly braces, so whitespace is part of the grammar. The problem is often invisible: a single space, a tab that looks like four spaces, or a non-breaking space copied from a web page.
I reproduced every case below with Python 3.11.17, 3.13.5, 3.14.8 and 3.15.0rc3 on Linux, plus Ruff 0.17.3 and Black 26.10.1. Every output block is copied from those runs, and the error text was the same on all four versions unless I say otherwise.
In this guide:
- What the error looks like
- Why Python cares about indentation
- Cause 1: a stray space at the start of a top-level line
- Cause 2: an extra indent inside a function or loop
- Cause 3: you commented out an if, for or def but not its body
- Cause 4: an indented line after a list, dict or function call
- Cause 5: pasting code with blank lines into the Python REPL
- Cause 6: running an indented string with exec() or a template
- Cause 7: mixing tabs and spaces (TabError)
- Cause 8: unindent does not match any outer indentation level
- Cause 9: an empty block (expected an indented block)
- Cause 10: invisible non-breaking spaces from copied code
- How to find indentation problems fast
- Editor settings that prevent it (VS Code and others)
- Quick fix checklist
- Related guides and tools
- Frequently asked questions
What the error looks like
Here's the smallest file that triggers it. The second line starts with two spaces:
name = "Mahir"
print("Hello,", name)
Running it with python3 c1_unexpected.py on Python 3.13.5 gives:
File "/workspace/seo-posts-nov02/test/python/c1_unexpected.py", line 2
print("Hello,", name)
IndentationError: unexpected indent
Three things matter here. The file name and line number tell you where Python gave up. The line it prints is shown without its leading whitespace, so you can't see the problem in the message itself. And because this is a syntax-level error, Python stops before running a single line, so no print() output appears even for lines above the bad one.
Remove the two spaces and the script works:
Hello, Mahir
Why Python cares about indentation
Python's tokenizer tracks the indentation of every logical line on a stack. A line that is indented more than the previous one is only allowed straight after a line that opens a block, such as if x:, for item in items:, def f():, class A:, with ...: or try:. When a line dedents, it must return to a column that is already on the stack. The rules are spelled out in the Python lexical analysis reference.
Those rules produce three related errors, and they need slightly different fixes:
| Message | What Python saw | Usual fix |
|---|
IndentationError: unexpected indent | A line indented more than the line above, without a colon line opening a block | Remove the extra leading whitespace |
IndentationError: unindent does not match any outer indentation level | A line dedented to a column no outer block uses | Line it up with the block it belongs to |
IndentationError: expected an indented block after ... | A colon line with no indented body under it | Indent the body, or add pass |
TabError: inconsistent use of tabs and spaces in indentation | Tabs and spaces mixed so the meaning depends on tab width | Convert the file to spaces only |
TabError is a subclass of IndentationError, which itself is a subclass of SyntaxError, so a broad except SyntaxError around compile() or exec() catches all of them.
Cause 1: a stray space at the start of a top-level line
This is the example above, and it's the most common version. Top-level code (anything not inside a function, class or block) must start in column 0. One accidental space from a sloppy paste, or from a deleted if line, is enough.
Fix: put your cursor at the start of the line Python reports and delete everything before the first character. If the line looks fine, turn on visible whitespace in your editor, because the extra character might be a tab or a special space (see cause 10).
Cause 2: an extra indent inside a function or loop
Inside a block, every statement at the same level must start in exactly the same column. Here, the for line is pushed four spaces too far right:
def total(prices):
result = 0
for p in prices:
result += p
return result
print(total([3, 4, 5]))
File "/workspace/seo-posts-nov02/test/python/c2_block.py", line 3
for p in prices:
IndentationError: unexpected indent
Python points at line 3 because result = 0 on line 2 doesn't end in a colon, so nothing allowed line 3 to go deeper. Notice that the line after the bad one is also wrong (the loop body isn't indented under the for), but Python only reports the first problem.
Fix: move for back to the same column as result = 0 and keep its body four spaces deeper:
def total(prices):
result = 0
for p in prices:
result += p
return result
print(total([3, 4, 5]))
12
Cause 3: you commented out an if, for or def but not its body
This one catches people while debugging. You comment out a condition to "always run" the code, but the body is still indented:
debug = True
# if debug:
print("debug mode on")
File "/workspace/seo-posts-nov02/test/python/c9_commented.py", line 3
print("debug mode on")
IndentationError: unexpected indent
Comments are invisible to the parser, so Python sees debug = True followed by an indented print().
Fix: either restore the if line, or dedent the body when you comment out its header. A temporary if True: also keeps the structure intact.
Cause 4: an indented line after a list, dict or function call
Multi-line brackets let you indent however you like, because Python ignores indentation inside (), [] and {}. The trap is the line after the closing bracket, which goes back to normal rules:
colors = [
"red",
"green",
]
print(len(colors))
File "/workspace/seo-posts-nov02/test/python/c8_after_list.py", line 5
print(len(colors))
IndentationError: unexpected indent
Many editors auto-indent after a closing bracket, so it's easy to miss. (If you're still choosing between bracket types, my comparison of list vs tuple vs set vs dict explains when each one fits.)
Fix: start the next statement in the same column as colors = [.
Cause 5: pasting code with blank lines into the Python REPL
The classic interactive shell treats an empty line as "this block is finished". Paste a function that has a blank line inside it and the rest of the function arrives as a new, wrongly indented statement. I simulated a paste through a pseudo-terminal on Python 3.11.17:
>>> def area(w, h):
... result = w * h
...
>>> return result
File "<stdin>", line 1
return result
IndentationError: unexpected indent
>>>
>>> print(area(3, 4))
None
>>>
Look at the last line: area() was defined without its return, so it quietly returned None. I got the identical result on Python 3.13.5 with the classic shell (PYTHON_BASIC_REPL=1).
The new interactive shell in Python 3.13 and later handles this much better. When I sent the same text as a bracketed paste (what a modern terminal does when you press Ctrl+Shift+V), it accepted the whole block and printed 12. The What's New in Python 3.13 page also describes a "paste mode" on F3 for larger blocks.
Fix: on Python 3.13+, use the default REPL and paste normally, or press F3 first. On older versions, remove blank lines inside functions before pasting, or save the code to a .py file and run it instead.
Cause 6: running an indented string with exec() or a template
Code stored in a triple-quoted string usually inherits the indentation of the surrounding source. When you pass it to exec(), compile() or a tool that runs snippets, Python sees indented top-level code:
code = """
total = 2 + 3
print("total is", total)
"""
exec(code)
Traceback (most recent call last):
File "/workspace/seo-posts-nov02/test/python/c7_exec.py", line 5, in <module>
exec(code)
~~~~^^^^^^
File "<string>", line 2
total = 2 + 3
IndentationError: unexpected indent
The File "<string>" line is the clue: the bad indentation is inside the string, not in your file. Python 3.11.17 printed the same traceback without the ~~~~^^^^^^ marker line.
Fix: strip the common leading whitespace with textwrap.dedent() before running the code:
import textwrap
code = """
total = 2 + 3
print("total is", total)
"""
exec(textwrap.dedent(code))
total is 5
Cause 7: mixing tabs and spaces (TabError)
A tab doesn't have a fixed width. Python treats it as moving to the next multiple of 8 columns, while your editor might show it as 2 or 4. Because that makes the meaning ambiguous, Python 3 refuses files where the indentation only works for some tab widths. Here, line 2 uses four spaces and line 3 uses one tab:
def check(age):
if age >= 18:
return "adult"
return "minor"
print(check(20))
On Python 3.13.5 this fails with:
File "/workspace/seo-posts-nov02/test/python/c4_tab.py", line 3
return "adult"
^
TabError: inconsistent use of tabs and spaces in indentation
Python 3.11.17 gave the same message without the caret line. In most editors, the source above looks perfectly aligned, which is why this error feels unfair. cat -A on Linux or macOS shows the tab as ^I:
def check(age):$
if age >= 18:$
^Ireturn "adult"$
return "minor"$
$
print(check(20))$
Fix: convert the whole file to spaces. PEP 8 says "Spaces are the preferred indentation method" and that Python disallows mixing them with tabs. On the command line, expand -t 8 c4_tab.py > fixed.py replaced the tab with 8 spaces, which matches how Python reads it, and the fixed file printed adult. In an editor, use the "convert indentation to spaces" option described in the editor section below.
Cause 8: unindent does not match any outer indentation level
This sibling error appears when a line moves left, but not far enough to land on a column that an outer block uses. The last print() here is at 6 spaces, while the function body is at 4 and the if body at 8:
def greet(name):
if name:
print("Hi", name)
print("done")
greet("Mahir")
File "/workspace/seo-posts-nov02/test/python/c3_unindent.py", line 4
print("done")
^
IndentationError: unindent does not match any outer indentation level
The caret at the end of the line is misleading. The problem is the start of the line.
Fix: decide which block the line belongs to and match that column exactly. Here it should run after the if, so it moves to 4 spaces, and the script prints Hi Mahir then done. If the columns look identical but the error stays, you have tabs and spaces mixed (cause 7).
Cause 9: an empty block (expected an indented block)
The opposite mistake: a line ends in a colon, but nothing indented follows. A comment alone doesn't count as a body:
def save_user(user):
# TODO: write to database
print("saved")
File "/workspace/seo-posts-nov02/test/python/c5_expected.py", line 4
print("saved")
^^^^^
IndentationError: expected an indented block after function definition on line 1
The same happens with a loop whose body isn't indented, which gave IndentationError: expected an indented block after 'for' statement on line 1. Since Python 3.10, the message names the statement and its line, which makes this one quick to track down.
Fix: indent the body, or add a placeholder. Both pass and ... worked and printed saved:
def save_user(user):
# TODO: write to database
pass
print("saved")
Cause 10: invisible non-breaking spaces from copied code
Code copied from a web page, PDF, chat app or word processor sometimes contains a non-breaking space (U+00A0) instead of a normal space. It looks identical, but Python doesn't count it as indentation at all:
File "/workspace/seo-posts-nov02/test/python/c6_nbsp.py", line 2
return 3.14159 * r * r
^
SyntaxError: invalid non-printable character U+00A0
This one isn't an IndentationError, but people hit it while trying to fix indentation, so it belongs here. grep -nP '\xA0' c6_nbsp.py found it on line 2.
Fix: replace every U+00A0 with a normal space. This one-liner did it for me, and the fixed file printed 12.56636:
python3 -c "import pathlib; p=pathlib.Path('c6_nbsp.py'); pathlib.Path('f6_nbsp.py').write_text(p.read_text(encoding='utf-8').replace('\u00a0',' '), encoding='utf-8')"
How to find indentation problems fast
Running a big script just to find a whitespace mistake is slow. These checks only parse the file:
| Tool | Command | What it showed in my tests |
|---|
| py_compile | python3 -m py_compile file.py | Sorry: IndentationError: unexpected indent (c2_block.py, line 3) |
| tabnanny | python3 -m tabnanny -v file.py | Flagged the tab line in both TabError files |
| Ruff 0.17.3 | ruff check file.py | Reported both broken lines in c2_block.py at once |
| Black 26.10.1 | black --check file.py | error: cannot parse: c2_block.py:3:0 |
| cat -A | cat -A file.py | Tabs as ^I, line ends as $ |
Ruff's output was the most useful, because it listed every problem instead of stopping at the first:
invalid-syntax: Unexpected indentation
--> c2_block.py:3:1
...
invalid-syntax: Expected an indented block after `for` statement
--> c2_block.py:4:9
...
Found 2 errors.
And here's tabnanny on the TabError file:
'c4_tab.py': *** Line 3: trouble in tab city! ***
offending line: '\treturn "adult"'
inconsistent use of tabs and spaces in indentation
Formatters can't repair a file that doesn't parse, but once it's valid, ruff format converted a tab-indented file to 4-space indentation for me.
Editor settings that prevent it (VS Code and others)
Most indentation errors start in the editor. According to the VS Code basic editing docs, VS Code inserts spaces and uses 4 spaces per Tab key by default, and it auto-detects the indentation of each open file. The detected setting appears in the Status Bar, and clicking it lets you convert between tabs and spaces.
- Set
"editor.insertSpaces": true and "editor.tabSize": 4 for Python files. - Turn on
"editor.renderWhitespace": "all" while debugging so tabs and stray spaces become visible. - If a file keeps fighting you, click the indentation item in the Status Bar and convert the file to spaces.
I didn't test the VS Code menus on this box; these are the settings VS Code documents.
Quick fix checklist
- Go to the exact line number in the error.
- Delete all leading whitespace on that line and re-indent it to match its neighbours.
- Check the line above: does it end with a colon? If not, the line can't be deeper.
- Check for a commented-out
if, for or def above it. - Show whitespace in your editor and convert the file to spaces.
- Run
python3 -m py_compile or ruff check to catch the next problem without running the script. - If the message mentions
<string>, dedent the string with textwrap.dedent().
Once your script runs, the next error you meet might be about imports rather than whitespace. My guide to ModuleNotFoundError: No module named covers that one with the same tested approach.
Related guides and tools
The free tools on mfaysal.com include a word counter and other quick browser utilities.
Frequently asked questions
What does IndentationError: unexpected indent mean?
It means a line starts further right than Python expects. A line can only be indented more than the one above it when that line opens a block with a colon, such as if, for, def or class. Otherwise Python stops before running anything.
How do I fix unexpected indent in Python quickly?
Go to the line number in the error, delete the leading whitespace and re-indent it to match the lines around it. Then check that the line above ends in a colon if you meant to start a new block.
What is the difference between unexpected indent and expected an indented block?
Unexpected indent means a line has too much indentation. Expected an indented block means a line ending in a colon has no indented body at all. The fix for the second one is to indent the body or add pass.
Why do I get TabError when my code looks aligned?
Your file mixes tabs and spaces. A tab can look like four spaces in your editor while Python treats it as moving to the next multiple of 8 columns. Convert the file to spaces only, for example with your editor's convert indentation command or expand -t 8.
How many spaces should I use for indentation in Python?
Use 4 spaces per level. PEP 8 recommends 4 spaces and says spaces are the preferred indentation method. Python itself accepts any consistent amount, but 4 is what almost every project and formatter uses.
Why does my code work in a file but fail in the Python shell?
The classic REPL treats a blank line as the end of a block, so pasting a function with an empty line inside breaks it. Python 3.13 and later have a new shell that handles pastes, and an F3 paste mode.
Can an IndentationError be caught with try and except?
Only when the code is compiled at runtime, for example with exec(), compile() or importing another module. Then except SyntaxError catches it, because IndentationError and TabError are subclasses. An error in the file you are running stops Python before your try block exists.
Can Black or Ruff fix indentation errors automatically?
Not while the file has a syntax error. In my tests Black reported cannot parse and Ruff reported invalid-syntax. Once you fix the broken line, ruff format or Black will normalise the rest of the file to 4-space indentation.
Last checked: 2 November 2026. Figures, settings and guidance can change, so confirm anything important with the sources linked above.