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_EXCLflags 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
8. Handle Symlink Race Conditions
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')
"
Related Error Codes
- EACCES (errno 13) — Permission denied
- ENOENT (errno 2) — No such file or directory
- ENOTEMPTY (errno 39) — Directory not empty
Comments