Python raises FileNotFoundError when code asks the OS to open or use a file or directory at a path that does not exist there. The traceback usually reads [Errno 2] No such file or directory, so the Python exception and the “No such file or directory” message describe the same problem. The official docs map it to errno.ENOENT. Below: typical causes, how to read the traceback, concrete fixes (pathlib, absolute paths, checks, try / except, creating parent folders), the tricky “file exists but Python still can’t open it” cases (working directory, symlinks, permissions, directories), and how notebooks and IDEs differ from the terminal.
Tested on: Python 3.13.3; kernel 6.14.0-37-generic.
What is FileNotFoundError in Python?
FileNotFoundError is a built-in exception (a subclass of OSError). It appears when operations such as open(), Path.read_text(), or libraries that wrap them need a real file or directory on disk, but the OS reports that nothing exists at the resolved path.
The traceback often ends with [Errno 2] No such file or directory on many systems: errno 2 is ENOENT on POSIX. Always read the path string at the end of the error line and compare it to what you expect on disk.
Minimal example: opening a name that is not present at the path Python resolves:
with open("this_file_does_not_exist.txt", "r", encoding="utf-8") as f:
f.read()Traceback (most recent call last):
File "script.py", line 1, in <module>
with open("this_file_does_not_exist.txt", "r", encoding="utf-8") as f:
~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
FileNotFoundError: [Errno 2] No such file or directory: 'this_file_does_not_exist.txt'Save the two-line snippet as script.py in an empty folder and run python script.py; your File "…" line will show your real path. Python 3.11+ often adds a caret line under the failing call.
"No such file or directory" vs FileNotFoundError
If you searched for “python no such file or directory” you are looking at the same thing as FileNotFoundError. “No such file or directory” is the operating system’s text for error number 2 (ENOENT); when Python hits that errno from a file operation, it raises FileNotFoundError and prints the OS message after [Errno 2]. Messages such as python can't open file 'app.py': [Errno 2] No such file or directory are the same error coming from the interpreter trying to open the script you named.
So every fix below applies whether you see the exception name in a traceback or just the raw “No such file or directory” line in a terminal.
Why FileNotFoundError happens
Common reasons:
- Wrong file name (typo, wrong language, stale name after a rename).
- Wrong extension (for example
.txtvs.csv, or a double extension on Windows such asreport.csv.txt). - File lives in another folder than the path you passed.
- A relative path is resolved from the process current working directory (
cwd), which is not always the folder that contains your script or notebook. - Writing to
out/results.txtwhen theoutparent folder was never created. - Windows vs Linux/macOS differences: case sensitivity, drive letters, backslash vs slash, tilde
~not expanded in plain strings.
Fix 1: Check the file path
The first step is to confirm the exact path Python is using, not the path you assumed. Re-read the traceback path, then check that path on disk (or print it in code with repr(path) so spaces and odd characters are visible).
Compare spelling and extension character by character with the real file. Mixing config.json and configs.json, or Data.csv and data.csv on a case-sensitive filesystem, triggers this error. On Windows, Explorer can hide known extensions: a file can look like report.csv while the real name is report.csv.txt. Prefer pathlib or tab-complete in the terminal to see the full name.
Relative paths are resolved from os.getcwd(), not from the folder that contains your .py file unless you build paths that way. open("data/config.json") looks for data/config.json under the cwd. Print what the process sees:
import os
from pathlib import Path
print("cwd:", os.getcwd())
p = Path("data/config.json")
print("as given:", p)
print("resolved:", p.resolve())If resolved points somewhere unexpected, fix how you start the program (cd in the shell, run configuration “working directory” in the IDE, or notebook kernel cwd) or stop relying on bare relative strings without anchoring (see Fix 2 and Fix 3).
Fix 2: Use an absolute path
An absolute path starts from the filesystem root (drive or /) and is useful to prove whether the file exists where you think it does. If an absolute path works but a relative one fails, the problem is usually cwd or how the relative string was built.
Linux and macOS examples:
from pathlib import Path
home_doc = Path("/home/alice/documents/notes.txt") # adjust user
etc_hosts = Path("/etc/hosts")Windows examples (pick one style; raw strings avoid escaping backslashes):
from pathlib import Path
p1 = Path(r"C:\Users\alice\data\input.csv")
p2 = Path("C:/Users/alice/data/input.csv") # often works in pathlibTilde alone in a string is not expanded; use Path.home() or os.path.expanduser:
from pathlib import Path
docs = Path.home() / "Documents" / "readme.md"Fix 3: Build paths with pathlib
pathlib.Path is usually clearer than manual string concatenation: it reduces slash mistakes and reads well across platforms.
from pathlib import Path
root = Path("/var/app") # or Path.home() / "myproject"
cfg = root / "config" / "settings.json"
data = root / "data" / "rows.csv"Anchor to the script directory when data ships next to the module:
from pathlib import Path
HERE = Path(__file__).resolve().parent
input_csv = HERE / "data" / "input.csv"For more patterns, see check if a file exists and write to file in Python. Join path segments with os.path.join when you stay on string-based os.path APIs.
Fix 4: Check if the file exists before opening
Use a guard when a missing file is an expected case: optional config, a path from user input, or startup validation. Path.is_file() avoids opening a path that is not a regular file.
from pathlib import Path
path = Path("local_settings.json")
if path.is_file():
text = path.read_text(encoding="utf-8")
else:
text = "{}" # defaultDo not wrap every read in exists() if missing should be exceptional; in that case a failed open or a narrow except FileNotFoundError is often clearer.
Fix 5: Handle FileNotFoundError with try/except
When the file may or may not exist and the program should continue, catch the exception narrowly so other I/O errors still surface.
from pathlib import Path
path = Path("cache.json")
try:
blob = path.read_text(encoding="utf-8")
except FileNotFoundError:
blob = "{}"See try / except and catch multiple exceptions.
Fix 6: Create missing folders before writing files
Creating out/report.txt fails if out does not exist. Create parents first—see create nested directories in Python:
from pathlib import Path
out = Path("out") / "report.txt"
out.parent.mkdir(parents=True, exist_ok=True)
out.write_text("hello", encoding="utf-8")FileNotFoundError but the file exists
A very common, frustrating case is “the file is right there, but Python says No such file or directory.” Almost always the file exists at a path that is different from the one Python actually resolves. Print the resolved path first, then check the cases below.
from pathlib import Path
target = "data/report.csv"
print("resolved:", Path(target).resolve())
print("exists :", Path(target).exists())Wrong working directory (relative path)
This is the number one cause. A relative path like data/report.csv is resolved against the process working directory (os.getcwd()), not the folder that holds your .py file. The file exists next to your script, but you launched Python from a different directory. Anchor the path to the script instead:
from pathlib import Path
HERE = Path(__file__).resolve().parent
report = HERE / "data" / "report.csv"
print(report.exists())Broken symbolic link
A symlink that points to a missing target raises FileNotFoundError even though the link itself “exists” in the listing. Resolve and validate the link before opening:
import os
from pathlib import Path
p = Path("broken_link.txt")
if p.is_symlink():
print("link points to:", os.readlink(p))
print("target exists :", p.exists()) # False if the target is goneOpening a broken link shows the same message as a missing file:
FileNotFoundError: [Errno 2] No such file or directory: 'broken_link.txt'p.is_symlink() is True for the link, but p.exists() is False because it follows the link to a target that is not there. Recreate the target or repoint the link.
Permission denied on a parent directory
If a parent directory is not searchable (no execute bit) you may not even be able to confirm the file, and the call typically raises PermissionError rather than FileNotFoundError. Treat a [Errno 13] Permission denied as “exists but blocked,” and fix directory permissions or run as a user with access; see the error table below.
Hidden or trailing characters in the file name
A trailing space, a non-breaking space, or a Unicode look-alike in the name makes "data .csv" a different path from "data.csv", so the open fails although the file “looks” correct:
FileNotFoundError: [Errno 2] No such file or directory: 'data .csv'Use tab-completion in a shell, or list the directory from Python and compare repr(name) to reveal stray characters:
from pathlib import Path
for entry in Path(".").iterdir():
print(repr(entry.name))The path is a directory, not a file
If the path resolves to a folder, open() raises IsADirectoryError, not FileNotFoundError—a related mix-up worth ruling out when you “know” the path exists. Guard with is_file() / is_dir():
from pathlib import Path
p = Path("subdir")
if p.is_dir():
print("This is a directory, not a file.")
elif p.is_file():
print(p.read_text(encoding="utf-8"))
else:
print("Path does not exist:", p)Opening a directory directly looks like this:
IsADirectoryError: [Errno 21] Is a directory: 'subdir'FileNotFoundError in Jupyter Notebook or IDE
Jupyter often uses the notebook’s folder as cwd; a path that works when you cd to the repo root in a terminal may fail in a cell without changing directory or without anchoring paths.
In VS Code or PyCharm, the run/debug configuration can set a working directory that differs from the integrated terminal. If the script “works in terminal but not when I click Run,” compare cwd (Fix 1) and prefer paths built from Path(__file__).parent or a documented project root.
FileNotFoundError vs similar errors
| Error | Meaning |
|---|---|
FileNotFoundError |
File or directory path does not exist for this operation |
PermissionError |
Path exists but the process is denied for the requested operation |
IsADirectoryError |
You used open() (or similar) on a path that is a directory |
ModuleNotFoundError |
Import machinery cannot find a module or package (import foo), not the same as a missing path for open() |
Official reference: FileNotFoundError.
Common mistakes
- Treating
open("data/x.csv")as relative to the script file; it is relative to cwd unless you build the path from__file__or a known root. - Wrong or hidden file extension, especially on Windows.
- Writing without creating parent directories first.
- Using
"C:\new\file.txt"without a raw string or doubled backslashes so\nbecomes a newline escape inside the path. - Catching
Exception(or a broad tuple) and masking real bugs; preferFileNotFoundErrorwhen only “missing file” should be handled.
Python FileNotFoundError cheat sheet
| Symptom | What to try first |
|---|---|
Error right after open("foo") |
Does foo exist under os.getcwd()? Print Path("foo").resolve(). |
| Works in IDE, fails in terminal | Compare cwd and run configuration working directory. |
| Works locally, fails after deploy | Missing asset or different job cwd; use anchored paths or env-based roots. |
| Only on Windows | Hidden extension, backslashes, drive-relative paths. |
| On write | path.parent.mkdir(parents=True, exist_ok=True) before write_text / open(..., "w"). |
CSV example paths use the same rules; see read and write CSV.
Summary
FileNotFoundError means nothing exists at the path the OS used for that call, shown as [Errno 2] No such file or directory / ENOENT—so it is the same problem whether you see the exception name or just the raw message. Verify the path string in the traceback, then narrow down spelling, extension, cwd vs relative paths, Windows vs POSIX details, and missing parent folders. When the file “exists” but Python still fails, check the working directory, broken symlinks, hidden or trailing characters in the name, a path that is really a directory, and permission errors on parents. Prefer pathlib, absolute paths for debugging, optional is_file() checks, targeted except FileNotFoundError, and mkdir(parents=True) before writes. Related: delete file, custom exceptions.

