OSError: [Errno 36] File name too long in Python (tested)

OSError: [Errno 36] File name too long (ENAMETOOLONG) means one path component is over 255 bytes or the whole path is over 4096 bytes on Linux. Non-ASCII names hit the limit sooner because UTF-8 uses several bytes per character. Shorten the name by bytes and add a hash to keep it unique.

1. The error

name = "report_" + "x" * 250 + ".csv"
print(len(name))
open(name, "w")

Output:

261
Traceback (most recent call last):
  File "/tmp/ln372/b1.py", line 3, in <module>
    open(name, "w")
    ~~~~^^^^^^^^^^^
OSError: [Errno 36] File name too long: 'report_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.csv'

The file name is 261 characters. Linux filesystems such as ext4 allow at most 255 bytes per path component (NAME_MAX), so open() fails with ENAMETOOLONG. This usually happens when a file name is built from user input, a URL, a page title or a long list of parameters.

2. The limit is 255 bytes, not 255 characters

import os
print(os.pathconf(".", "PC_NAME_MAX"), os.pathconf(".", "PC_PATH_MAX"))
ok = "a" * 255
open(ok, "w").close()
print("255 bytes: ok")
os.remove(ok)
# 128 characters, but each "é" is 2 bytes in UTF-8
name = "é" * 128
print(len(name), "chars,", len(name.encode()), "bytes")
try:
    open(name, "w")
except OSError as e:
    print(type(e).__name__, e.errno, e.strerror)

Output:

255 4096
255 bytes: ok
128 chars, 256 bytes
OSError 36 File name too long

Exactly 255 ASCII bytes works. But 128 characters of é is 256 bytes in UTF-8 and fails, so a len(name) <= 255 check is not enough for non-ASCII names (accents, CJK, emoji). Check len(name.encode()) instead. os.pathconf(".", "PC_NAME_MAX") reports the limit for the filesystem you are on.

3. The whole path is too long (PATH_MAX 4096)

import os
# each component is only 200 bytes, but the whole path is > 4096 (PATH_MAX)
path = "/".join(["d" * 200] * 21) + "/f.txt"
print(len(path))
try:
    os.makedirs(os.path.dirname(path))
except OSError as e:
    print(type(e).__name__, e.errno, e.strerror, "| len(filename) =", len(e.filename))
depth = 0
p = "d" * 200
while os.path.isdir(p):
    depth += 1
    p = os.path.join(p, "d" * 200)
print("directories created before the failure:", depth)

Output:

4226
OSError 36 File name too long | len(filename) = 4220
directories created before the failure: 20

Each component here is only 200 bytes, but the full path passed to the kernel may not exceed 4096 bytes (PC_PATH_MAX). os.makedirs created 20 levels and then failed on the 21st, so it leaves a partial tree behind. Deeply nested generated directories (cache keys, mirrored URLs) are the usual cause.

4. Fix: shorten the name by bytes and add a hash

import hashlib, os

def safe_filename(name, max_bytes=255):
    """Shorten name to fit NAME_MAX bytes, keeping the extension and a hash."""
    if len(name.encode()) <= max_bytes:
        return name
    stem, ext = os.path.splitext(name)
    digest = hashlib.sha1(name.encode()).hexdigest()[:10]
    budget = max_bytes - len(ext.encode()) - len(digest) - 1
    short = stem.encode()[:budget].decode("utf-8", "ignore")
    return f"{short}-{digest}{ext}"

for n in ["report.csv", "report_" + "x" * 250 + ".csv", "é" * 200 + ".txt"]:
    s = safe_filename(n)
    print(len(n.encode()), "->", len(s.encode()), s[-20:])
    open(s, "w").close(); os.remove(s)

Output:

10 -> 10 report.csv
261 -> 255 xxxxx-5c000bdbbb.csv
404 -> 255 ééééé-c8a0a30f55.txt

Truncate the UTF-8 bytes, decode with "ignore" so a multi-byte character is not cut in half, keep the extension, and append a short hash of the full name so two long names that share a prefix do not collide. If you need the original name, store it in a sidecar file or database instead of in the file name.

5. Catch it precisely

import errno
try:
    open("y" * 300, "w")
except OSError as e:
    print(type(e).__name__, e.errno == errno.ENAMETOOLONG, errno.errorcode[e.errno])

Output:

OSError True ENAMETOOLONG

It is a plain OSError with no dedicated subclass; check e.errno == errno.ENAMETOOLONG.

Related: [Errno 22] Invalid argument · [Errno 2] No such file or directory · [Errno 39] Directory not empty.

Frequently asked questions

What is the maximum file name length on Linux?

255 bytes per component on ext4 and most Linux filesystems, and 4096 bytes for the whole path. os.pathconf('.', 'PC_NAME_MAX') and 'PC_PATH_MAX' report them.

Why does a 130-character name fail?

The limit counts UTF-8 bytes. Accented letters take 2 bytes and CJK characters 3, so 128 'é' characters are already 256 bytes.

How do I catch Errno 36?

except OSError as e: if e.errno == errno.ENAMETOOLONG. There is no dedicated subclass.

Written with AI assistance. Measured on 2026-10-23 with Python 3.13.5 on Linux (Debian 13, ext4). Each block was run verbatim and the output pasted unedited. PlainTables is our extension; Python is free.