Informix Error -29
-29 Illegal seek.
An operating-system error code with the meaning shown was unexpectedly returned to the database server. Look for other operating-system error messages that might give more information, such as the device on which the error occurred. 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 29 is ESPIPE — Illegal seek. A seek was attempted on something that cannot be seeked.
Unix objects divide into two kinds for this purpose:
| Seekable | Not seekable |
|---|---|
| Regular files | Pipes and FIFOs |
| Block devices | Sockets |
| Tape, through its own interface | Terminals |
A seekable object has a position you can move to arbitrarily. A stream does not — data arrives once, in order, and what has passed is gone. lseek() on a pipe is not a failure of the pipe; it is a request that has no meaning.
The distinction from -22:
- -29
ESPIPE— the object cannot be seeked at all - -22
EINVAL— the object is seekable and the offset was unacceptable
So -29 says something about the plumbing; -22 says something about the arithmetic.
What This Means in Informix
This error is uncommon in Informix's own operation, and it is worth saying why.
The obvious suspicion — that piping a backup breaks it — is wrong. ontape reading and writing through -t STDIO is a supported arrangement, and archive and restore are sequential operations. They read and write forward and do not need to position within the stream. A piped backup and a piped restore are both fine:
ontape -s -L 0 -t STDIO | gzip -c > /backups/archive_L0.gz
gunzip -c /backups/archive_L0.gz | ontape -r -t STDIO
Neither of those produces -29, and reaching for -29 after a backup failure is usually the wrong direction — -32 (broken pipe) or -28 (no space) are far more likely from a pipeline.
Where -29 does appear, it is almost always something around Informix rather than the engine: a wrapper, a custom utility, or application code that assumed a seekable descriptor and was handed a stream.
The usual shape
The commonest source is code that wants a file's size and takes it by seeking to the end:
size = lseek(fd, 0, SEEK_END); /* fails with ESPIPE on a pipe */
lseek(fd, 0, SEEK_SET);
That works in testing, where the input is a file, and fails in production, where the same program is fed from a pipe. The pattern turns up in:
- Backup and housekeeping wrappers that report or check sizes
- Custom loaders and unload processors in an ESQL/C or 4GL estate
- Anything reading from standard input that also wants to re-read or measure it
- External-table processing through a named pipe, where the consuming program makes more than one pass
FIFOs
A named pipe is a stream. It supports a single forward pass and nothing else. Where a FIFO has been configured somewhere a file was expected, any program that positions, re-reads, or measures will fail — and a FIFO in a device parameter is worth checking for that reason even if nothing is failing yet (see -25 and -6 for the other ways that misconfiguration surfaces).
Common Causes
- A program measuring size with
lseek(fd, 0, SEEK_END)on an input that turns out to be a pipe. - Code that re-reads or rewinds its input, given a stream.
- A named pipe where a file or device was expected.
- A utility reading standard input that assumes it can position within it.
- A wrapper tested against files and deployed against pipes.
Diagnostic Checks
Determine what the descriptor actually is. /proc/<pid>/fd names the kind directly:
ls -l /proc/<pid>/fd
# 3 -> /backups/archive_L0 <- regular file, seekable
# 4 -> pipe:[482113] <- pipe, not seekable
# 5 -> socket:[482119] <- socket, not seekable
For a path rather than a descriptor:
stat -c '%F %n' /path/to/target
ls -l /path/to/target # leading 'p' = FIFO
Find the failing seek, which also names the descriptor:
strace -f -e trace=lseek /path/to/command 2>&1 | grep ESPIPE
# lseek(4, 0, SEEK_END) = -1 ESPIPE (Illegal seek)
# ^ cross-reference against /proc/<pid>/fd
# ^ SEEK_END usually means "how big is this?"
The whence argument is informative: SEEK_END is almost always a size check, SEEK_SET a rewind or a re-read.
# Solaris / AIX
truss -f -t lseek /path/to/command 2>&1 | grep -i espipe
Find the pattern in source, where you have it:
grep -rn -E 'lseek\s*\(|fseek\s*\(|rewind\s*\(|ftell\s*\(' /path/to/src
grep -rn 'SEEK_END' /path/to/src
Check configured devices for a FIFO where a file or device belongs:
for p in $(awk '/^(TAPEDEV|LTAPEDEV)/ {print $2}' "$INFORMIXDIR/etc/$ONCONFIG"); do
printf '%-40s %s\n' "$p" "$(stat -c '%F' "$p" 2>/dev/null || echo MISSING)"
done
Solutions / Resolution
- Identify what the descriptor is before anything else. One
ls -l /proc/<pid>/fdsettles whether the operation was ever possible. - Do not assume a descriptor is seekable. Where the code is yours, test and take a forward-only path when it is not:
if (lseek(fd, 0, SEEK_CUR) == (off_t)-1 && errno == ESPIPE) { /* stream: single forward pass, no size check */ } - Get size from the filesystem, not by seeking, where the input may be a stream —
stat()on the path, or accumulate a byte count as you read. - Feed a file rather than a pipe to a program that genuinely needs to position. If the data arrives compressed, decompress to a file first and hand it the file.
- Do not use a FIFO where anything makes more than one pass.
- Test wrappers with piped input, not only with files. This failure exists almost entirely because the two were never exercised the same way.
Examples
A size check on a stream
$ strace -f -e trace=lseek -p 9912 2>&1 | grep ESPIPE
[pid 9912] lseek(0, 0, SEEK_END) = -1 ESPIPE (Illegal seek)
$ ls -l /proc/9912/fd/0
lr-x------ 1 ifxprod ifxprod 64 Sep 9 04:02 /proc/9912/fd/0 -> pipe:[482113]
Descriptor 0 is standard input, and it is a pipe. SEEK_END on it is a size check. The program was written expecting a file argument and is now being fed from a pipeline; nothing about permissions, storage or the data is wrong.
A FIFO where a file was configured
$ for p in $(awk '/^(TAPEDEV|LTAPEDEV)/ {print $2}' "$INFORMIXDIR/etc/$ONCONFIG"); do
> printf '%-40s %s\n' "$p" "$(stat -c '%F' "$p" 2>/dev/null || echo MISSING)"
> done
/dev/st0 character special file
/informix/backups/logpipe fifo
The logical-log device is a named pipe. Sequential writing to it is fine; anything that positions or re-reads is not. Worth knowing about deliberately rather than discovering later.
Platform Note
errno 29 is ESPIPE on Linux, AIX, Solaris, HP-UX and the BSD-derived systems — stable, so the number is reliable, and the seekable/not-seekable division is a property of the object rather than a platform choice.
Inspecting descriptors is not portable:
| Task | Linux | Solaris | AIX |
|---|---|---|---|
| What is this descriptor | ls -l /proc/<pid>/fd |
pfiles <pid> |
procfiles <pid> |
| Trace seeks | strace -e trace=lseek |
truss -t lseek |
truss -t lseek |
| Identify a FIFO | stat -c '%F', ls -l |
ls -l, file |
istat, ls -l |
pfiles on Solaris is particularly direct here — it reports the type of each open descriptor alongside its flags, which is exactly the question this error raises.
Related Errors / Related Topics
- -22 — Invalid argument. The other seek failure: the object is seekable and the offset was not acceptable. If the target turns out to be a regular file, read that one instead.
- -32 — Broken pipe. The error a pipeline actually tends to produce, and a far more likely explanation for a failed piped backup than this one.
- -6 — No such device or address, which a FIFO produces when opened for writing with no reader.
- -14 — Bad address. The other error that usually indicates application code rather than configuration.
A -29 almost always points at a program that was written for files and is being given a stream. The engine's own sequential operations do not produce it, so the code around Informix is the place to look.