How to Fix FileNotFoundError: [Errno 2] No such file or directory

3D isometric cyber-tech graphic comparing the FileNotFoundError [Errno 2] "The Problem" with "The Fix" using pathlib in Python.

Last Updated: October 2026

Tested On: Python 3.14 | Windows 11 | Ubuntu 26.04 LTS | macOS 26

Part of: The Ultimate Python Debugging Guide

When Python throws a FileNotFoundError, it means the operating system cannot locate the file or directory you requested at the specific path provided. Unlike module imports (which raise ModuleNotFoundError), this is an OS-level file system error. It almost always stems from a misunderstanding of your current working directory, relative pathing, or system case sensitivity.

The Traceback

Read the traceback from the bottom up. The last line states the error, and the line above it shows the exact file operation that failed.

Traceback (most recent call last):
  File "/var/www/app/data_loader.py", line 4, in <module>
    with open('config.json', 'r') as f:
FileNotFoundError: [Errno 2] No such file or directory: 'config.json'

⚡ The Quick Fix

Python evaluates relative paths (like 'config.json') based on the directory from which you executed the script in your terminal, not the directory where the script file physically lives.

To fix this immediately and ensure the path resolves relative to the script’s location, use the pathlib module to build a dynamic path.

from pathlib import Path

# 1. Anchor the path to the current script's location
base_dir = Path(__file__).resolve().parent

# 2. Safely join the path to the target file
file_path = base_dir / 'data' / 'config.json'

with open(file_path, 'r') as file:
    config = file.read()
    print("Success!")

(Note: If you are quickly debugging, you can also hardcode an absolute path like /var/www/app/data/config.json or C:/app/data/config.json, but avoid leaving absolute paths in production code).

🛠️ The Ultimate Diagnostic Command

If you swear the file is right next to your Python script, but Python still throws a file error, your execution context is misaligned or the filename is slightly off. Run this diagnostic block to expose the mismatch:

import os

# 1. Shows where your terminal/IDE is currently executing the code from
print("Working Directory:", os.getcwd())

# 2. Shows where this specific Python file is physically located
# (Note: __file__ raises a NameError in Jupyter Notebooks. Use Path.cwd() instead).
print("Script Location:", os.path.dirname(os.path.abspath(__file__)))

# 3. Lists actual files in the working directory to expose typos or hidden extensions
print("Files in Directory:", os.listdir(os.getcwd()))

# 4. Prints the raw string representation of your path variable to expose trailing spaces
# (Replace my_path_variable with the exact variable you are passing to open())
my_path_variable = 'data.csv '
print("Raw Target String:", repr(my_path_variable))

If the Working Directory and Script Location do not match exactly, any relative path you write (e.g., open('data.csv')) will look inside the Working Directory, entirely ignoring where the script is saved.

📋 Common Causes & Fixes

Before writing complex path-handling code, verify you have not made one of these standard file system errors:

  • The Execution Directory Trap (IDEs & Cron): You have a script inside /src/scripts/ but executed it from the root /src/ folder via terminal (python scripts/main.py). The script looks for files in /src/, not /src/scripts/. This also happens heavily in automated environments: VS Code often runs from the workspace root, while PyCharm defaults to the script’s folder (depending on your IDE’s run configuration). Cron and Windows Task Scheduler run from ~ or C:\Windows\System32 by default.
  • Windows Backslash Escapes: A path like 'C:\new\table.csv' will fail with a mangled path error (often OSError: [Errno 22] Invalid argument) because Python converts \n and \t into control characters. Even worse, paths like 'C:\Users\admin' will crash immediately with a SyntaxError: (unicode error) because \U expects a Unicode escape.
    • Fix: Use forward slashes (C:/new/table.csv), which work perfectly with Python’s standard open() on Windows, or use raw strings (r'C:\new\table.csv'). Note that raw strings cannot end in a single backslash.
  • Subprocess Executable Missing: If you see FileNotFoundError: [Errno 2] No such file or directory: 'git', you are using the subprocess module, and the executable you are trying to run is not installed or not in your system’s PATH environment variable.
  • Typos and Hidden Extensions: Windows hides known file extensions by default. If you created a text file and named it data.csv, Windows actually saved it as data.csv.csv or data.csv.txt.
  • OS Case Sensitivity: You wrote your code on macOS or Windows and it worked perfectly (open('Data.csv')). You deployed it to a Linux server, and it crashed. Windows and macOS file systems are case-insensitive by default, but Linux file systems are strictly case-sensitive. Data.csv and data.csv are two completely different files on Linux.
  • Tilde (~) Expansion: Using open('~/data.csv') fails because the standard open() function does not interpret ~ as the user’s home directory.
    • Fix: Use Path('~/data.csv').expanduser().
  • Opening a File in ‘w’ Mode (Truncation Warning): Opening a file in write mode ('w') automatically creates the file if it does not exist (provided the parent folder exists). However, it will also instantly erase (truncate) an existing file.
    • Fix: If you want to create a file but explicitly fail if it already exists, use 'x' mode (exclusive creation, which raises FileExistsError). If you just want to ensure a file exists without altering it, use Path('file.txt').touch(exist_ok=True).
  • Windows Path Length Limits: On older Windows setups, paths exceeding 260 characters can trigger this error. You may need to enable Long Paths in the Windows Registry or use the raw string prefix r'\\?\C:\...'.

The Modern Fix: Use pathlib

pathlib is recommended for new code over the older os.path module. It represents paths as smart objects rather than simple strings, allowing you to elegantly join paths using the forward slash / operator.

For Standard Python Scripts:

from pathlib import Path

# Get the absolute path of the directory containing this script
BASE_DIR = Path(__file__).resolve().parent
file_path = BASE_DIR / 'data' / 'config.json'

with open(file_path, 'r') as file:
    pass

For Jupyter Notebooks & REPL:

Jupyter Notebooks do not define __file__ or the interactive Python shell. If you are working in a Notebook, use Path.cwd() to get the current working directory instead:

from pathlib import Path
file_path = Path.cwd() / 'data' / 'config.json'

FileNotFoundError in Pandas and Polars

In the Data Science ecosystem, loading datasets via pd.read_csv() raises the standard Python FileNotFoundError.

Polars runs on a Rust engine, so its missing-file error reads differently from pandas’.. If a file is missing, Polars’ error text differs from Pandas’ and may explicitly mention (os error 2) depending on your installed version.

Because Jupyter Notebooks automatically set the working directory to the folder containing the .ipynb file, moving your code from a Notebook to a standard .py pipeline often breaks your relative paths, triggering these missing file exceptions in both libraries.

The Fix:

Anchor your data directories using pathlib to ensure your pipelines remain portable.

import pandas as pd
import polars as pl
from pathlib import Path

# Anchor to the project root (assuming the script is in /src)
PROJECT_ROOT = Path(__file__).resolve().parent.parent
dataset_path = PROJECT_ROOT / 'datasets' / 'sales.csv'

df = pd.read_csv(dataset_path)
df_polars = pl.read_csv(dataset_path)

How to Safely Check if a File Exists

If you are dealing with optional configuration files, do not assume the file exists. Using an if file_path.exists(): check right before opening a file creates a race condition (the file could be deleted by another process in the millisecond between the check and the open() call).

Instead, use a try/except block to catch the FileNotFoundError safely:

from pathlib import Path
import logging

file_path = Path('optional_settings.json')

try:
    # Use pathlib's built-in .read_text() for clean, one-line file reading
    data = file_path.read_text(encoding='utf-8')
except FileNotFoundError:
    logging.warning("File %s not found. Proceeding with default settings.", file_path)
    data = "{}"

Frequently Asked Questions

Why does Python say FileNotFoundError when I can see the file right there?

Python looks for relative paths starting from the directory where you typed the python command in your terminal, not the directory where the .py script is saved. Use import os; print(os.getcwd()) to see where Python is currently looking.

How do I fix FileNotFoundError [Errno 2] in a Docker container?

Your Docker container has its own isolated file system. If you get this error inside Docker, verify four things:

1. Check your .dockerignore file to ensure the file isn’t being explicitly excluded.
2. Verify your COPY commands use paths relative to the Docker build context.
3. Ensure your WORKDIR is set correctly before running your script.
4. Check your bind mounts (volume mounts) in docker-compose.yml. A volume mount will overwrite the directory where you COPYed the file, completely hiding it from the container if the host folder is empty.

Does open(file, 'w') throw a FileNotFoundError?

Opening a file in write ('w') or append ('a') mode automatically creates the file if it does not exist. However, if the parent directory is missing (e.g., open('missing_folder/file.txt', 'w')), it will throw a FileNotFoundError.

What is the difference between os.path and pathlib?

os.path treats paths as raw strings and uses functions like os.path.join(). pathlib treats paths as intelligent objects, handling OS-specific slashes automatically and allowing cleaner syntax like Path('folder') / 'file.txt'. pathlib is recommended for new Python code.

Similar Posts

Leave a Reply