Informix Error -18
-18 Cross-device link.
An operating-system error code with the meaning shown was unexpectedly returned to the database server. If the error recurs, note all circumstances and contact IBM Informix Technical Support.
Oninit® Troubleshooting Guidance
This is an operating-system error number, not an Informix diagnosis.
The same errno is returned by many different operations, so on its own it says what the operating system refused, not what Informix was trying to do. Informix will usually have reported a more specific error alongside it — in the message log, in the SQL or ISAM error pair, or in the accompanying assert failure — and that error normally defines the real cause far more precisely than the errno does. Find it before diagnosing from this number alone.
This matters less than it used to. Later versions of the engine trap many of these conditions and report them as specific Informix errors naming the operation, the object and the context, so a bare errno in this range is increasingly a sign of an older version, an unusual code path, or a failure early in startup before the better reporting is available. If you are seeing one on a current version, the more specific error is worth looking for even harder.
Operating-System Meaning
errno 18 is EXDEV — Invalid cross-device link. An operation that can only work within a single filesystem was asked to span two.
Two calls produce it:
rename()— moving or renaming a path from one filesystem to anotherlink()— creating a hard link whose target is on a different filesystem
Neither is a limitation that can be configured away. A hard link is a second directory entry pointing at the same inode, and inode numbers are only meaningful within one filesystem; rename() is defined to be atomic, which it cannot be if the data has to be copied.
This causes confusion because the shell's mv appears to work across filesystems. It does — by falling back to copy-then-delete when rename() returns EXDEV. So a script using mv succeeds where a program calling rename() directly fails, and the same logical operation behaves differently depending on how it was written.
That fallback matters for more than convenience:
rename()within a filesystem is atomic. Copy-then-delete across filesystems is not. Anything relying on rename for atomicity loses that guarantee the moment the source and destination are on different filesystems — whether it fails with -18 or silently falls back.
What This Means in Informix
The write-temp-then-rename pattern
The common idiom for producing a file safely is to write it under a temporary name and rename it into place once complete, so readers never see a partial file. That only works if the temporary and the final path are on the same filesystem.
This breaks quietly when:
TMPDIRor a hard-coded/tmpis a separate filesystem from the output directory/tmpistmpfs— a different filesystem by definition- The output directory is a mount and the staging directory is on the root filesystem
- A container writes to
/tmpinside the image while the destination is a mounted volume
The failure mode is worth stating plainly: either the operation errors with -18, or it falls back to a copy and the atomicity the pattern existed to provide is gone. Readers can then see a half-written file.
Backup and log-archive movement
- Moving completed logical log backups from a staging directory to archive storage on a different filesystem
- Relocating
ontapeoronbaroutput after completion - Rotating
online.loginto an archive area on another mount - Moving unload or
dbexportoutput after generation
Hard-link-based schemes
rsync --link-destand similar snapshot-style backups, which depend on hard links and cannot span filesystems- Deduplication or versioning schemes that link rather than copy
- Any script using
ln(without-s) across mounts
A symbolic link has none of these restrictions — ln -s works across filesystems — which is often the correct substitution when a hard link was chosen without needing inode identity.
Common Causes
- Temporary and destination directories on different filesystems in a write-then-rename pattern.
- A script moving backup output from staging to archive storage across a mount boundary.
- A hard link attempted across filesystems, often in a snapshot or dedup scheme.
/tmpbeingtmpfswhile the target is on disk.- Container filesystem boundaries — image layers versus mounted volumes.
- A new mount introduced under a path that previously sat on one filesystem, so a script that worked for years begins failing.
Diagnostic Checks
The definitive check is the device number. Two paths on the same filesystem share it:
stat -c '%d %n' /path/to/source /path/to/destination
df -h /path/to/source /path/to/destination
findmnt -T /path/to/source
findmnt -T /path/to/destination
Different values in the first column mean rename() and link() cannot work between them, whatever the paths look like.
Check the directories a script actually uses, rather than the ones it appears to use:
echo "TMPDIR=[$TMPDIR]"
stat -c '%d %n' "${TMPDIR:-/tmp}" /path/to/output/dir
mount | grep -E ' /tmp | /var/tmp '
findmnt -t tmpfs
/tmp on tmpfs is its own filesystem and will never share a device number with a directory on disk.
Find the boundary in the middle of a path:
findmnt -T /informix/backups/staging
findmnt -T /informix/backups/archive
lsblk -o NAME,SIZE,MOUNTPOINT
Confirm which call failed, if the script's behaviour is unclear:
strace -f -e trace=rename,renameat,renameat2,link,linkat /path/to/script 2>&1 | grep EXDEV
For Informix-specific paths, check whether the directories involved are on one filesystem:
grep -nE 'TAPEDEV|LTAPEDEV|DUMPDIR' "$INFORMIXDIR/etc/$ONCONFIG"
stat -c '%d %n' "$INFORMIXDIR/tmp" /informix/backups /informix/archive 2>/dev/null
Solutions / Resolution
- Establish the filesystem boundary with
stat -c '%d'. This takes one command and settles whether the operation was ever possible. - Put the temporary file in the destination filesystem, not in
/tmp. This is the correct fix for the write-then-rename pattern, and it restores the atomicity as well as removing the error:# instead of staging in /tmp tmp=$(mktemp "/informix/backups/archive/.tmp.XXXXXX") produce_output > "$tmp" mv "$tmp" /informix/backups/archive/output.unl # same filesystem: atomic - Use copy-then-remove deliberately where the move genuinely must cross filesystems, and handle the consequences — verify the copy before removing the source, and be aware that readers can see a partial file unless you stage within the destination first.
- Substitute a symbolic link where a hard link was used without needing inode identity.
ln -scrosses filesystems freely. - For hard-link snapshot schemes, keep the source and the link target on one filesystem. This is a layout decision, not something the tooling can work around.
- Set
TMPDIRexplicitly in scripts rather than relying on inheritance, so the staging location is known rather than incidental. - Re-check after any storage change. A script that has worked for years will start failing the day a new mount is introduced beneath a path it uses.
Examples
Staging in /tmp, writing to a mount
$ stat -c '%d %n' /tmp /informix/backups/archive
23 /tmp
66 /informix/backups/archive
Different devices. A script writing to /tmp/export.tmp and renaming into /informix/backups/archive/ cannot work with rename(). Staging inside the archive directory instead fixes the error and makes the final move atomic:
tmp=$(mktemp /informix/backups/archive/.export.XXXXXX)
/tmp is tmpfs
$ findmnt -t tmpfs
TARGET SOURCE FSTYPE OPTIONS
/tmp tmpfs tmpfs rw,nosuid,nodev
/dev/shm tmpfs tmpfs rw,nosuid,nodev
$ stat -c '%d %n' /tmp /informix/unload
0 /tmp
66 /informix/unload
/tmp is memory-backed. Nothing on disk will ever share its device number, so any rename out of /tmp fails — and separately, anything large staged there is consuming RAM.
A mount introduced under a working path
$ findmnt -T /informix/backups/staging
TARGET SOURCE FSTYPE
/informix /dev/mapper/vg-informix xfs
$ findmnt -T /informix/backups/archive
TARGET SOURCE FSTYPE
/informix/backups/archive nas01:/export/archive nfs4
Both paths sit under /informix and look like one tree. The archive directory is an NFS mount added later, so a script that moved files between them for years began failing at the point that mount appeared. Nothing in the script changed.
A hard link across filesystems
$ ln /informix/backups/archive/log_0001 /informix/snapshots/daily/log_0001
ln: failed to create hard link: Invalid cross-device link
$ stat -c '%d %n' /informix/backups/archive /informix/snapshots/daily
66 /informix/backups/archive
71 /informix/snapshots/daily
A snapshot scheme using hard links to avoid duplicating data. Hard links cannot span filesystems; either bring both directories onto one filesystem or accept the copy.
Platform Note
errno 18 is EXDEV on Linux, AIX, Solaris, HP-UX and the BSD-derived systems — stable, so the number is reliable, and the underlying restriction is a property of how filesystems work rather than a platform choice.
Checking device identity differs slightly:
| Task | Linux | Solaris | AIX |
|---|---|---|---|
| Device number of a path | stat -c '%d' |
stat -c '%d', ls -lLd + df |
istat, df |
| Which filesystem holds a path | findmnt -T |
df -k <path> |
df <path> |
| List memory filesystems | findmnt -t tmpfs |
df -F tmpfs |
lsfs -v |
Some filesystems and some platforms permit rename() between distinct subvolumes or datasets of the same underlying pool, and others do not. On ZFS and Btrfs in particular, two paths that appear to be in one pool can still be different filesystems for this purpose, and stat -c '%d' remains the reliable test rather than reasoning about the storage layout.
Related Errors / Related Topics
- -28 — No space left on device. A cross-filesystem move that falls back to copying needs space in the destination that a rename would not have required; the two errors can appear in sequence from the same script.
- -2 — No such file or directory, where a path in the operation does not exist at all.
- -13 — Permission denied, worth ruling out where the filesystems do turn out to match.
Where -18 appears in a backup or housekeeping job, the layout is the finding. Scripts tend to encode filesystem assumptions implicitly, and a mount added anywhere beneath the paths they use will surface them all at once.