IsADirectoryError: [Errno 21] Is a directory (tested)
IsADirectoryError: [Errno 21] Is a directory means a function that works on files was given a directory path. We measured the four ways that usually happens on Python 3.13.5, with the fix for each.
1. open() on a directory, in any mode
import os
os.makedirs("reports", exist_ok=True)
for mode in ["r", "w", "a"]:
try:
open("reports", mode)
except IsADirectoryError as e:
print(f"open(dir, {mode!r}):", e)
from pathlib import Path
try:
Path("reports").read_text()
except IsADirectoryError as e:
print("read_text:", e)
Output:
open(dir, 'r'): [Errno 21] Is a directory: 'reports'
open(dir, 'w'): [Errno 21] Is a directory: 'reports'
open(dir, 'a'): [Errno 21] Is a directory: 'reports'
read_text: [Errno 21] Is a directory: 'reports'
Measured on Python 3.13.5 (Linux): reading, writing and appending all raise IsADirectoryError: [Errno 21] Is a directory, as does Path.read_text(). The path you passed points at a folder, not a file inside it. On Windows the same mistake usually shows up as PermissionError: [Errno 13] Permission denied instead (not tested here).
2. An empty filename in os.path.join
import os
folder = "reports"
name = "" # e.g. empty from a form/config
path = os.path.join(folder, name)
print(repr(path))
try:
open(path, "w")
except IsADirectoryError as e:
print(e)
# fix: make sure there is a filename
name = name or "report.txt"
with open(os.path.join(folder, name), "w") as f:
f.write("ok")
print("wrote", os.path.join(folder, name))
Output:
'reports/'
[Errno 21] Is a directory: 'reports/'
wrote reports/report.txt
Measured: os.path.join("reports", "") gives 'reports/', the folder itself. This is the usual cause when the filename comes from a form field, config value, URL path or split() result that turned out empty. Validate the name (or fall back to a default) before opening.
3. Looping over a folder that contains subfolders
import os, glob
os.makedirs("data/sub", exist_ok=True)
open("data/a.csv", "w").write("1\n")
for name in sorted(os.listdir("data")): # includes the subdirectory
try:
open(os.path.join("data", name)).read()
print("read", name)
except IsADirectoryError as e:
print("failed:", e)
for p in sorted(glob.glob("data/*")):
if os.path.isfile(p): # fix: skip directories
print("file:", p)
Output:
read a.csv
failed: [Errno 21] Is a directory: 'data/sub'
file: data/a.csv
Measured: os.listdir and glob("*") return subdirectories along with files. Filter with os.path.isfile(), use glob("*.csv") with an extension, or Path.glob(...) plus p.is_file().
4. Deleting or copying a directory with file functions
import shutil, os
os.makedirs("src", exist_ok=True)
try:
os.remove("src")
except IsADirectoryError as e:
print("os.remove(dir):", e)
try:
shutil.copy("src", "dst")
except IsADirectoryError as e:
print("shutil.copy(dir):", e)
os.rmdir("src") # empty dir; shutil.rmtree for non-empty
print("os.rmdir: removed")
Output:
os.remove(dir): [Errno 21] Is a directory: 'src'
shutil.copy(dir): [Errno 21] Is a directory: 'src'
os.rmdir: removed
Measured: os.remove and shutil.copy only handle files. Use os.rmdir (empty directory), shutil.rmtree (with contents) or shutil.copytree for folders.
Frequently asked questions
What does IsADirectoryError: [Errno 21] Is a directory mean?
You passed a folder path to something that needs a file: open(), Path.read_text(), os.remove() or shutil.copy(). We measured each on Python 3.13.5.
Why do I get Is a directory when writing a file?
The path ends at a folder, often because the filename part was empty: we measured os.path.join('reports', '') returning 'reports/'. Check the filename before opening.
How do I skip directories when reading all files in a folder?
Filter with os.path.isfile() or Path.is_file(), or glob a specific extension. We measured os.listdir returning a subfolder that then failed to open.
How do I delete a directory in Python?
os.rmdir for an empty directory, shutil.rmtree for one with contents. We measured os.remove on a directory raising IsADirectoryError.
Is it IsADirectoryError or PermissionError on Windows?
On Windows, opening a directory typically raises PermissionError [Errno 13] instead. We only measured Linux, which raises IsADirectoryError [Errno 21].
Written with AI assistance. Measured on 2026-10-09 with Python 3.13.5 on Linux: open() on a directory in r/w/a modes, Path.read_text, os.path.join with an empty name, os.listdir with a subfolder, os.remove and shutil.copy on a directory. Every block was run verbatim and its output pasted from that run. Windows was not tested. PlainHeaders is our extension; everything else here is built-in Python.