# How to Fix Python OSError: [Errno]

The OSError is a broad exception class that wraps system-level errors returned by the operating system. These errors include file operations, network issues, and other OS-level failures, identified by specific errno codes.

Error Patterns

File Not Found (errno 2)

text
Traceback (most recent call last):
  File "app.py", line 3, in <module>
    os.remove("missing.txt")
OSError: [Errno 2] No such file or directory: 'missing.txt'

Permission Denied (errno 13)

text
Traceback (most recent call last):
  File "app.py", line 5, in <module>
    open("/etc/shadow", "w")
PermissionError: [Errno 13] Permission denied: '/etc/shadow'

Directory Not Empty (errno 39)

text
Traceback (most recent call last):
  File "app.py", line 7, in <module>
    os.rmdir("nonempty_dir")
OSError: [Errno 39] Directory not empty: 'nonempty_dir'

Too Many Open Files (errno 24)

text
Traceback (most recent call last):
  File "app.py", line 10, in <module>
    open(f"file_{i}.txt")  # Loop creating many files
OSError: [Errno 24] Too many open files

Network Errors

text
Traceback (most recent call last):
  File "app.py", line 15, in <module>
    socket.connect((host, port))
OSError: [Errno 111] Connection refused

Common Errno Codes

ErrnoNameDescription
2ENOENTNo such file or directory
13EACCESPermission denied
17EEXISTFile exists
22EINVALInvalid argument
24EMFILEToo many open files
28ENOSPCNo space left on device
30EROFSRead-only file system
39ENOTEMPTYDirectory not empty
54ECONNRESETConnection reset by peer
111ECONNREFUSEDConnection refused
113EHOSTUNREACHNo route to host

Common Causes

  1. 1.Missing files/directories - Path doesn't exist
  2. 2.Permission issues - Insufficient access rights
  3. 3.Disk full - No storage space available
  4. 4.Too many open files - Exceeded system limits
  5. 5.Invalid file names - Illegal characters or length
  6. 6.Read-only filesystem - Cannot write to location
  7. 7.Network failures - Connection issues
  8. 8.Resource limits exceeded - System limits reached

Diagnosis Steps

Step 1: Check Errno and Message

```python import os import errno

try: os.remove("missing.txt") except OSError as e: print(f"Errno: {e.errno}") print(f"Message: {e.strerror}") print(f"Filename: {e.filename}")

# Compare with known errno values if e.errno == errno.ENOENT: print("File not found") elif e.errno == errno.EACCES: print("Permission denied") ```

Step 2: Check System State

```bash # Linux/Mac diagnostics df -h # Disk space ls -la filename # File permissions lsof -p $$ # Open files for current process ulimit -n # File descriptor limit cat /proc/sys/fs/file-max # System max files

# Windows dir filename # File info wmic logicaldisk # Disk space ```

Step 3: Check File/Directory State

```python import os from pathlib import Path

path = Path("target_file")

# Check existence print(f"Exists: {path.exists()}")

# Check permissions print(f"Readable: {os.access(path, os.R_OK) if path.exists() else 'N/A'}") print(f"Writable: {os.access(path, os.W_OK) if path.exists() else 'N/A'}") print(f"Executable: {os.access(path, os.X_OK) if path.exists() else 'N/A'}")

# Check parent directory parent = path.parent print(f"Parent exists: {parent.exists()}") print(f"Parent writable: {os.access(parent, os.W_OK) if parent.exists() else 'N/A'}") ```

Solutions

Solution 1: Handle FileNotFoundError (errno 2)

```python import os from pathlib import Path

# Problem: File doesn't exist os.remove("missing.txt") # OSError errno 2

# Fix: Check before operation path = Path("missing.txt") if path.exists(): path.unlink() else: print("File not found, skipping removal")

# Or use try/except try: os.remove("missing.txt") except FileNotFoundError: # Subclass of OSError print("File not found") except OSError as e: print(f"Other error: {e}") ```

Solution 2: Handle PermissionError (errno 13)

```python import os

# Problem: No permission with open("/etc/shadow", "w"): # OSError errno 13

# Fix: Check permissions first path = "/etc/shadow" if os.access(path, os.W_OK): with open(path, "w") as f: f.write("data") else: print("No write permission") # Ask for elevated permissions or use different path

# Fix: Use user-accessible path user_path = os.path.expanduser("~/output.txt") with open(user_path, "w") as f: f.write("data") ```

Solution 3: Handle Directory Not Empty (errno 39)

```python import os import shutil

# Problem: Cannot remove non-empty directory os.rmdir("nonempty_dir") # OSError errno 39

# Fix: Use shutil.rmtree for non-empty directories shutil.rmtree("nonempty_dir") # Removes directory and contents

# Or check and handle path = "nonempty_dir" if os.path.isdir(path): if os.listdir(path): # Directory has contents shutil.rmtree(path) else: os.rmdir(path) ```

Solution 4: Handle Too Many Open Files (errno 24)

```python import os

# Problem: Opening too many files without closing files = [] for i in range(10000): files.append(open(f"file_{i}.txt")) # OSError errno 24

# Fix: Close files after use for i in range(10000): with open(f"file_{i}.txt") as f: # Auto-closes content = f.read()

# Fix: Increase file descriptor limit import resource soft, hard = resource.getrlimit(resource.RLIMIT_NOFILE) resource.setrlimit(resource.RLIMIT_NOFILE, (hard, hard)) # Increase limit

# Fix: Use file pooling from contextlib import ExitStack with ExitStack() as stack: files = [stack.enter_context(open(f"file_{i}.txt")) for i in range(100)] # All files closed when ExitStack exits ```

Solution 5: Handle Disk Full (errno 28)

```python import os

# Problem: No space left on device with open("large_file", "w") as f: f.write(large_data) # OSError errno 28

# Fix: Check disk space before writing import shutil

def get_free_space(path): """Get free space in bytes.""" total, used, free = shutil.disk_usage(path) return free

def safe_write(path, data): """Write with disk space check.""" free = get_free_space(os.path.dirname(path)) required = len(data) + 1024 # Add buffer

if free < required: raise OSError(f"Insufficient disk space: {free} bytes free, {required} needed")

with open(path, "w") as f: f.write(data) ```

Solution 6: Handle Read-Only Filesystem (errno 30)

```python import os

# Problem: Cannot write to read-only filesystem with open("/mnt/cdrom/file.txt", "w") as f: # OSError errno 30

# Fix: Check filesystem mount options import subprocess

def is_readonly(path): """Check if filesystem is read-only.""" # Linux: check mount options mount_output = subprocess.run(['mount'], capture_output=True, text=True) for line in mount_output.stdout.split('\n'): if path in line and 'ro' in line: return True return False

# Use writable location if is_readonly("/mnt/cdrom"): write_path = "/tmp/output.txt" else: write_path = "/mnt/cdrom/file.txt" ```

Solution 7: Handle Network OSError

```python import socket

# Problem: Network errors sock = socket.socket() sock.connect(("unreachable.host", 80)) # OSError errno 113

# Fix: Handle network errors with retry import time

def connect_with_retry(host, port, retries=3, delay=1): sock = socket.socket() for attempt in range(retries): try: sock.connect((host, port)) return sock except OSError as e: if e.errno in (socket.ECONNREFUSED, socket.EHOSTUNREACH): if attempt < retries - 1: time.sleep(delay) continue raise return None

# Fix: Use timeout sock = socket.socket() sock.settimeout(5) # 5 second timeout try: sock.connect((host, port)) except socket.timeout: print("Connection timed out") ```

Solution 8: Handle Invalid Argument (errno 22)

```python import os

# Problem: Invalid filename (null byte, too long, etc.) open("file\x00name.txt") # OSError errno 22 (null byte in name) open("x" * 5000) # OSError errno 22 (name too long)

# Fix: Validate filename before use import re

def is_valid_filename(filename): """Check if filename is valid.""" # No null bytes if '\x00' in filename: return False # Not too long (most systems: 255 chars) if len(filename) > 255: return False # No invalid characters (depends on OS) if re.search(r'[<>:"|?*]', filename) and os.name == 'nt': # Windows return False return True

# Sanitize filename def sanitize_filename(filename): """Create safe filename.""" # Remove null bytes filename = filename.replace('\x00', '') # Truncate to valid length filename = filename[:255] # Remove Windows-invalid chars if os.name == 'nt': filename = re.sub(r'[<>:"|?*]', '_', filename) return filename ```

OSError Subclasses

Python provides specific subclasses for common OSError types:

```python # FileNotFoundError - errno 2 try: open("missing.txt") except FileNotFoundError: print("File not found")

# PermissionError - errno 13 try: open("/root/secret") except PermissionError: print("Permission denied")

# FileExistsError - errno 17 try: os.mkdir("existing_dir") except FileExistsError: print("Directory exists")

# IsADirectoryError - errno 21 try: open("directory_path") except IsADirectoryError: print("Path is a directory")

# NotADirectoryError - errno 20 try: os.listdir("file.txt") except NotADirectoryError: print("Path is not a directory")

# ConnectionError (network) try: socket.connect() except ConnectionError: print("Connection failed") ```

Cross-Platform Handling

```python import os import errno

def handle_os_error(e): """Handle OSError with platform awareness.""" error_map = { errno.ENOENT: "File/directory not found", errno.EACCES: "Permission denied", errno.EEXIST: "File already exists", errno.ENOSPC: "Disk full", errno.EROFS: "Read-only filesystem", errno.ENOTEMPTY: "Directory not empty", errno.EMFILE: "Too many open files", }

# Platform-specific codes if os.name == 'nt': # Windows win_errors = { 5: "Access denied", 32: "File in use", 183: "File already exists", } if hasattr(e, 'winerror') and e.winerror in win_errors: return win_errors[e.winerror]

return error_map.get(e.errno, str(e))

try: os.remove("some_file") except OSError as e: print(handle_os_error(e)) ```

Prevention Tips

  1. 1.Check existence before file operations
  2. 2.Check permissions before read/write
  3. 3.Use with statements for automatic cleanup
  4. 4.Validate paths before operations
  5. 5.Handle errors gracefully with specific exception types

```python import os from pathlib import Path

# Good pattern: Comprehensive file operation def safe_file_operation(path, operation): path = Path(path)

# Validate path if not is_valid_filename(path.name): raise ValueError(f"Invalid filename: {path.name}")

# Check parent exists if not path.parent.exists(): raise FileNotFoundError(f"Parent directory not found: {path.parent}")

# Check permissions if operation in ('w', 'a', 'x'): if not os.access(path.parent, os.W_OK): raise PermissionError(f"Cannot write to: {path.parent}")

# Perform operation with error handling try: return operation(path) except OSError as e: # Handle with context raise OSError(f"Failed {operation} on {path}: {e.strerror}") ```

  • FileNotFoundError - Specific for missing files
  • PermissionError - Specific for access denied
  • ConnectionError - Network-related OSError
  • IOError - Alias for OSError in Python 3