FileExistsError

Something is already at that path. It is the error you want from open(p, 'x') and the one you usually silence with exist_ok=True on mkdir.

InheritsBaseException›Exception›OSError›FileExistsError
OS exceptionPython 3.3+Live demo
FileExistsError(errnoerrno — errno.EEXIST when raised by the OS.type: int · default: null, strerror[, filename])
Raised by
os.mkdir(), Path.mkdir(), open(p, 'x'), os.link(), Windows os.rename()
Message
[Errno 17] File exists: 'path'
Quick fix
os.makedirs(p, exist_ok=True)
Watch out
exist_ok does not help when a FILE has that name

Demo

Live evaluation
Mode 'x' creates a file only if it does not exist yet. draft_1.txt is already there.
Try:
Inputs
nintdraft number
Code
from pathlib import Path
Path('draft_1.txt').write_text('v1')
n = 2
open(f'draft_{n}.txt', 'x').write('new draft')
Result
9

A successful open(..., 'x').write() returns the number of characters written; on an existing name it refuses instead of truncating — that is the whole point of 'x'. The Handle demo reads e.filename rather than str(e): os.mkdir's message text differs on Windows ([WinError 183]), but the class and filename do not.

Constructor

NameTypeRequiredDescription
errnointnoerrno.EEXIST when raised by the OS.
strerrorstrno'File exists' from open(); Windows os.mkdir gives 'Cannot create a file when that file already exists'.
filenamestr | bytes | NonenoThe path that already exists (for os.rename, the source; the target is filename2).

Attributes

AttributeTypeMeaning
errnoint | Noneerrno.EEXIST (17 on Linux, macOS and Windows).
strerrorstr | None'File exists' on POSIX and from open(); the Windows API text for os.mkdir and os.rename.
filenamestr | bytes | NoneThe path that was in the way.
filename2str | NoneFor os.rename / os.link: the destination path.

Common patterns

Create a folder if needed
exist_ok=True turns "already there" into success — no try/except, no race.
import os
os.makedirs('out/logs', exist_ok=True)
Never overwrite: exclusive create
Mode 'x' fails atomically if the file exists, so two processes cannot both think they created it.
try:
    with open('report.csv', 'x') as f:
        f.write(data)
except FileExistsError:
    print('report.csv exists, not overwriting')
Lock file
O_CREAT | O_EXCL is the classic cross-process lock: only one caller can create the file.
import os
try:
    fd = os.open('app.lock', os.O_CREAT | os.O_EXCL | os.O_WRONLY)
except FileExistsError:
    raise SystemExit('another instance is running')
Replace a file on every OS
os.rename raises FileExistsError on Windows when the target exists; os.replace overwrites everywhere.
import os
os.replace('report.tmp', 'report.csv')

Examples

1. open(..., 'x') on an existing file
from pathlib import Path Path('report.txt').write_text('v1') open('report.txt', 'x')
Returns
FileExistsError: [Errno 17] File exists: 'report.txt'
2. mkdir twice
import os os.mkdir('out') try: os.mkdir('out') except FileExistsError as e: r = e.filename r
Returns
'out'
3. makedirs with exist_ok=True
import os os.makedirs('out/logs', exist_ok=True) os.makedirs('out/logs', exist_ok=True) os.path.isdir('out/logs')
Returns
True
4. Path.mkdir(parents=True, exist_ok=True)
from pathlib import Path Path('a/b/c').mkdir(parents=True, exist_ok=True) Path('a/b/c').mkdir(parents=True, exist_ok=True) Path('a/b/c').is_dir()
Returns
True
5. exist_ok does not cover a file
from pathlib import Path Path('out').write_text('oops') try: Path('out').mkdir(exist_ok=True) except OSError as e: r = type(e).__name__ r
Returns
'FileExistsError'
6. errno EEXIST maps to it
import errno OSError(errno.EEXIST, 'File exists', 'a.txt')
Returns
FileExistsError(17, 'File exists')
7. os.replace overwrites everywhere
import os from pathlib import Path Path('new.txt').write_text('v2') Path('old.txt').write_text('v1') os.replace('new.txt', 'old.txt') (Path('old.txt').read_text(), os.path.exists('new.txt'))
Returns
('v2', False)

Pitfalls

1. 'w' silently overwrites
open(p, 'w') truncates an existing file without a word. When losing the old content would be a bug, use 'x' and handle FileExistsError.
mode 'w'
from pathlib import Path
Path('notes.txt').write_text('important')
open('notes.txt', 'w').write('draft')
Path('notes.txt').read_text()
'draft'
mode 'x'
from pathlib import Path
Path('notes.txt').write_text('important')
try:
    open('notes.txt', 'x').write('draft')
except FileExistsError:
    pass
Path('notes.txt').read_text()
'important'
2. Swallowing FileExistsError instead of exist_ok
except FileExistsError: pass assumes "the folder is already there". But a FILE with that name raises the same error — the folder you rely on does not exist. exist_ok=True only forgives an existing directory, so the file case still surfaces.
except: pass
import os
from pathlib import Path
Path('out').write_text('stray file')
try:
    os.makedirs('out')
except FileExistsError:
    pass  # 'already there, fine'
os.path.isdir('out')
False
exist_ok=True
import os
from pathlib import Path
Path('out').write_text('stray file')
try:
    os.makedirs('out', exist_ok=True)
    r = 'ready'
except FileExistsError:
    r = 'out is a file, not a folder'
r
'out is a file, not a folder'

When to use

Use it
  • Refusing to overwrite: open(p, 'x') and catch FileExistsError
  • Lock files and "first one wins" creation
  • Raising it from your own create-only API
Reach for something else
  • Folder may already exist → os.makedirs(p, exist_ok=True)
  • Overwrite on purpose → os.replace(src, dst)
  • Just checking → Path.exists()

Notes

CPython impl
Objects/exceptions.c — OSError(EEXIST, …) returns FileExistsError via the errno map
Catch via
except OSError
Platforms
os.rename onto an existing file raises FileExistsError on Windows but replaces silently on Linux/macOS; os.replace behaves the same everywhere

FAQ

Use os.makedirs(path, exist_ok=True) or Path(path).mkdir(parents=True, exist_ok=True). Both succeed when the directory is already there and still raise if something else is wrong.

History

3.3
Added, together with the other OSError subclasses (PEP 3151).