Informix Error -21
-21 Is a directory.
An operating-system error code with the meaning shown was unexpectedly returned to the database server. A file-type operation has been directed to a directory. Some database servers store tables, indexes, and lock files as files with particular suffixes in the database directory. If a directory replaced such a file, this error might result. Look for other operating-system error messages that might give more information.
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 21 is EISDIR — Is a directory. A file operation was directed at a directory.
This is the exact mirror of -20 (ENOTDIR, a file where a directory was needed), and the two share their causes: something created an object of the wrong type, or a path names something other than what the caller assumed.
One asymmetry explains why the error appears where it does:
Opening a directory for reading generally succeeds. Writing to one never does.
A program can open() a directory O_RDONLY on most systems — that is how directory listings work — so a path that is silently tolerated on a read will fail the moment anything writes. A configuration naming a directory where a file belongs can therefore pass startup checks and fail later, at the first write.
The other frequent source has nothing to do with Informix at all: shell redirection to a directory.
$ onstat -d > /informix/backups/
-bash: /informix/backups/: Is a directory
A missing filename, a variable that expanded to empty, or a trailing slash left in place produces exactly this.
What This Means in Informix
A directory where a file is expected
- A cooked chunk path naming a directory rather than the chunk file
TAPEDEVorLTAPEDEVpointing at a directory — a backup-to-disk setup where the parameter should name a file, or the intended filename was dropped- An unload,
dbexportor external-table output path given a directory MSGPATHorCONSOLEnaming a directory, so the engine cannot write its log- A restore or copy that created a directory where a file belongs — the counterpart of the flattening described on -20
The legacy file layout
The official text describes the older Standard Engine arrangement, where tables, indexes and lock files were stored as individual files with particular suffixes inside a dbname.dbs database directory. If one of those files has been replaced by a directory — usually by a restore, an extract or a partial copy — operations against that table produce this error.
Estates still running SE, or working with archived SE data, meet this in its original form. On a modern server the same shape appears wherever a configuration or a script expects a specific file and finds a directory instead.
Scripts
- Redirection with a missing or empty filename
- A variable expanding to a directory path because a suffix was not appended
- A trailing slash on what was meant to be a file path
Common Causes
- Shell redirection to a directory — the most common by a distance, and usually an empty variable.
- A configuration parameter naming a directory where a file is required.
- A directory created where a file belongs, by a restore, extract or copy.
- A path built by concatenation where the filename portion came out empty.
- A trailing slash on an intended file path.
Diagnostic Checks
Check what the target actually is. For a path with several components, the walking technique on -20 applies unchanged and will show the type of every level:
stat -c '%F %n' /path/to/target
ls -ld /path/to/target
namei -l /path/to/target
Find the empty-variable case, which rarely looks wrong in the source:
grep -n '> *"\?\$' /path/to/script.sh # redirects into a variable
bash -x /path/to/script.sh 2>&1 | grep -E '^\+.*>' | head
Running the script under bash -x shows the command line after expansion, which is where a missing filename becomes obvious.
Check the Informix parameters that must name files:
grep -nE 'TAPEDEV|LTAPEDEV|MSGPATH|CONSOLE|ROOTPATH' "$INFORMIXDIR/etc/$ONCONFIG"
for p in $(awk '/^(TAPEDEV|LTAPEDEV|MSGPATH|CONSOLE|ROOTPATH)/ {print $2}' \
"$INFORMIXDIR/etc/$ONCONFIG"); do
printf '%-40s %s\n' "$p" "$(stat -c '%F' "$p" 2>/dev/null || echo MISSING)"
done
Anything reporting directory against those parameters is the fault.
Check chunk paths for the same problem:
onstat -d | awk '/^[0-9]/ {print $NF}' | while read -r p; do
printf '%-45s %s\n' "$p" "$(stat -c '%F' "$(readlink -f "$p" 2>/dev/null)" 2>/dev/null || echo MISSING)"
done
In a legacy .dbs layout, look for directories carrying the names of what should be files:
find /path/to/dbname.dbs -maxdepth 1 -type d ! -name '*.dbs' -ls
If the failure is inside a program:
strace -f -e trace=open,openat,write /path/to/program 2>&1 | grep EISDIR
Solutions / Resolution
- Establish what created the directory before removing it. As on -20, the directory is often a symptom of a copy or restore that also failed to deliver its contents, and deleting it clears the error while leaving the real problem in place.
- Fix the script, not the filesystem, for the redirection case. Quote and validate the variable rather than relying on it:
Aout="${OUTDIR:?OUTDIR not set}/export_$(date +%Y%m%d).unl" onstat -d > "$out"${VAR:?}expansion fails loudly with a useful message instead of silently producing a directory path. - Correct configuration parameters to name files where files are required. For backup-to-disk, confirm what your version expects
TAPEDEVto be — a device, a file, or a directory — rather than assuming. - For a chunk path, never create a file inside the directory to make the error go away. Work out what the path should have been; a chunk pointed at the wrong object is worse than one that will not open.
- Re-run the failed copy or restore properly, since whatever should have been in that file is also missing.
- Remove a trailing slash where a file path carries one.
- Re-test the operation rather than the path.
Examples
An empty variable in a redirect
$ grep -n 'onstat' /informix/scripts/collect_stats.sh
42: onstat -d > "$STATSDIR/chunks_$(date +%F).txt"
$ bash -x /informix/scripts/collect_stats.sh 2>&1 | grep chunks
+ onstat -d
+ 1> /chunks_2026-09-09.txt
STATSDIR is unset, so the path resolved to the root directory — and in the variant where the date portion is also empty, the redirect lands on a directory and reports -21. The source line looks correct; only the expansion shows the fault.
TAPEDEV naming a directory
$ grep '^TAPEDEV' "$INFORMIXDIR/etc/$ONCONFIG"
TAPEDEV /informix/backups/
$ stat -c '%F' /informix/backups/
directory
The parameter names the directory the backup should go into rather than the target itself. Whether that is valid depends on the version and on how the backup is being taken — confirm what is expected before changing it, since both forms are plausible-looking.
A directory where a chunk file belongs
$ onstat -d | awk '/^[0-9]/ {print $NF}' | while read -r p; do
> printf '%-45s %s\n' "$p" "$(stat -c '%F' "$p" 2>/dev/null || echo MISSING)"
> done
/informix/chunks/rootdbs regular file
/informix/chunks/datadbs1 regular file
/informix/chunks/datadbs2 directory
datadbs2 is a directory. A restore recreated the path as a directory rather than restoring the chunk file, which means the chunk's contents were never restored either. Creating a file there would produce an empty chunk and a far more confusing failure than the one being reported.
Platform Note
errno 21 is EISDIR on Linux, AIX, Solaris, HP-UX and the BSD-derived systems — stable, so the number is reliable.
The read/write asymmetry described above is broadly consistent, but the details vary: some platforms and some filesystems refuse to open() a directory even for reading, where Linux permits it. Code that reads a path successfully on one platform can therefore fail earlier on another — which usually surfaces during a migration as an error appearing sooner rather than as a new problem.
Tooling for checking object types is the same set as -20: stat -c '%F' on Linux and Solaris, istat or ls -ld on AIX, and truss in place of strace.
Related Errors / Related Topics
- -20 — Not a directory. The exact mirror of this error, and where the path-walking technique is set out. Finding either one is good reason to look for the other, since both usually come from the same copy or restore.
- -2 — No such file or directory, where the object is missing rather than the wrong type.
- -13 — Permission denied, where the object is the right type and cannot be accessed.
- -15 — Block device required, the same class of type mismatch for device paths.
Where -21 follows a restore or a bulk copy, treat the affected object as one of several. The operation that created a directory in place of a file will usually have done it more than once, and the remaining instances are waiting on whatever next tries to write to them.