Linux EEXIST (errno 17) — File Exists

EEXIST (errno 17) means you tried to create a file or directory that already exists. This error appears when using open() with O_CREAT | O_EXCL, attempting mkdir() on an existing path, or creating a lock file that another process already created. It is common in scripts that generate temporary files, PID files, and socket files.

Common Causes

  • Target file or directory already exists at the specified path
  • Using O_CREAT | O_EXCL flags which enforce atomic creation
  • PID file already exists from a previous process instance
  • Temporary file was not cleaned up after a crash
  • Another process created the file between the check and creation
  • Symlink race condition on the target path

How to Fix EEXIST

1. Check If the File Exists First

Verify the path before attempting creation:

# Check if file exists
ls -la /path/to/file

# Check if directory exists
ls -d /path/to/directory

# Check from a script
if [ -e "/path/to/file" ]; then
    echo "File exists"
fi

2. Remove the Existing File Before Creating

Delete the stale file and recreate it:

# Remove the existing file
rm /path/to/file

# Remove directory and contents
rm -rf /path/to/directory

# Then create fresh
mkdir /path/to/directory
touch /path/to/file

3. Use O_EXCL Flag for Atomic Creation

The O_EXCL flag causes open() to fail if the file already exists, preventing race conditions:

int fd = open("/tmp/myfile", O_CREAT | O_EXCL | O_WRONLY, 0644);
if (fd == -1) {
    if (errno == EEXIST) {
        // File already exists — handle gracefully
    }
}

In bash:

# Atomic creation with O_EXCL via syscalls
python3 -c "
import os
fd = os.open('/tmp/myfile', os.O_CREAT | os.O_EXCL | os.O_WRONLY, 0o644)
os.write(fd, b'data')
os.close(fd)
"

4. Use mktemp for Safe Temporary Files

mktemp handles atomic creation automatically:

# Create a temporary file
TMPFILE=$(mktemp /tmp/myapp.XXXXXX)
echo "Created: $TMPFILE"

# Create a temporary directory
TMPDIR=$(mktemp -d /tmp/mydir.XXXXXX)
echo "Created: $TMPDIR"

# Create a temporary file with a specific extension
TMPFILE=$(mktemp /tmp/myapp.XXXXXX.log)

5. Handle PID File Conflicts

PID files commonly cause EEXIST on service restart:

# Check if the process in the PID file is still running
PIDFILE=/var/run/myapp.pid
if [ -f "$PIDFILE" ]; then
    PID=$(cat "$PIDFILE")
    if kill -0 "$PID" 2>/dev/null; then
        echo "Process $PID is still running"
    else
        echo "Stale PID file, removing"
        rm -f "$PIDFILE"
    fi
fi

6. Avoid Race Conditions with mkdir

mkdir() returns EEXIST if the directory is created between your check and creation:

# Race-condition prone (DO NOT use):
if [ ! -d "/tmp/mydir" ]; then
    mkdir /tmp/mydir  # May fail if another process just created it
fi

# Safe approach: just attempt mkdir and handle the error
mkdir /tmp/mydir 2>/dev/null || true

7. Use Temporary Filesystem for Staging

Create new files in /tmp first, then move atomically:

# Create in temp location
TMPFILE=$(mktemp /tmp/stage.XXXXXX)
echo "content" > "$TMPFILE"

# Move atomically to final location
mv -f "$TMPFILE" /path/to/final/file

Be aware that someone could replace a file with a symlink:

# Check for symlinks
ls -la /path/to/file

# Use lstat instead of stat to detect symlinks
python3 -c "
import os
try:
    os.lstat('/path/to/file')
    print('Path exists (may be symlink)')
except FileNotFoundError:
    print('Path is available')
"

Comments