EXDEV
Linux / POSIXERRORCommonFile SystemHIGH confidence

Invalid Cross-Device Link

Production Risk

Common in file upload pipelines — temp files are on tmpfs, final storage is on a different filesystem.

What this means

EXDEV (errno 18) is returned when rename() or link() is called with source and destination on different filesystems. Hard links and atomic renames cannot cross filesystem boundaries.

Why it happens
  1. 1Calling rename() with source and destination on different filesystems or mount points
  2. 2Calling link() (hard link) across filesystem boundaries
  3. 3Moving a file from /tmp (tmpfs) to /home (ext4) with a library that uses rename() internally
How to reproduce

Renaming a file from /tmp to /home on a different filesystem.

trigger — this will error
trigger — this will error
import os
os.rename('/tmp/upload.tmp', '/home/user/upload.jpg')
# OSError: [Errno 18] Invalid cross-device link

expected output

OSError: [Errno 18] Invalid cross-device link: '/tmp/upload.tmp' -> '/home/user/upload.jpg'

Fix

Copy then delete instead of rename across devices

WHEN When the source and destination are on different filesystems

Copy then delete instead of rename across devices
import shutil, os
shutil.copy2('/tmp/upload.tmp', '/home/user/upload.jpg')
os.unlink('/tmp/upload.tmp')
# Or use shutil.move() which handles EXDEV automatically

Why this works

shutil.move() detects EXDEV and falls back to copy+delete automatically. Use it instead of os.rename() when the destination may be on a different filesystem.

What not to do

Use os.rename() for moves that may cross filesystem boundaries

rename() is only atomic within the same filesystem. For cross-device moves, always use copy+delete or shutil.move().

Sources
Official documentation ↗

Linux Programmer Manual rename(2)

rename(2)

Content generated with AI assistance and reviewed for accuracy. Found an error? hello@errcodes.dev

← All Linux / POSIX errors