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.