Informix Error -110
-110 ISAM error: end or beginning of the file.
Reading rows sequentially, forward or backward, the ISAM processor has reached one end of the file (table). For C-ISAM programs, this message is the normal signal for end of file. Use a different retrieval mode of isread to reposition the file. For SQL products, see the SQL error message or return code.
Oninit® Troubleshooting Guidance
Reasons / Common Causes
-110 is different from everything else in this range so far: it isn't a defect condition at all. The official text says it plainly for C-ISAM — this is "the normal signal for end of file." Reading sequentially, forward or backward, eventually reaches one end of the data; -110 is how the ISAM processor reports that, not a failure.
The causes worth understanding are really about misreading this signal, not about triggering it:
- A perfectly ordinary sequential scan reaching its end. Every loop that calls
isread()withISNEXT(orISPREVreading backward) will eventually see -110 — that's the loop's correct termination condition, appearing exactly once per scan, every time. - Application code that treats -110 as an error — logging it, alerting on it, or surfacing it to a user as a failure — when it's simply "there was nothing more to read." This is the single most common actual problem associated with -110: not the condition itself, but code that doesn't recognize it as normal.
- Continuing to read past the point -110 was already returned, without repositioning the
file first. Every subsequent
isread(ISNEXT)after reaching the end keeps returning -110 — it isn't a one-time signal that clears itself; the file stays positioned at the end until something (ISFIRST,ISLAST, a keyedISCURR, orisstart()) repositions it. - A scan that reaches -110 much earlier than expected — not because -110 itself is wrong,
but because the underlying data, key range, or starting position wasn't what the code assumed.
The row count is genuinely smaller than expected, a key-range restriction narrowed the scan
more than intended, or the starting position (
isstart()) placed the cursor further along than the code assumed. - Confusing this with SQL's own NOTFOUND condition. SQL/ESQL code typically sees the
standard
SQLCODE 100/sqlca.sqlcodeNOTFOUND signal at the end of aFETCHloop; -110 is the ISAM-level equivalent, reached directly only by code calling the ISAM API itself (or visible as background/secondary information under the SQL layer's own handling). Treating -110 as a separate condition to react to, on top of the SQL layer's own NOTFOUND, is redundant and a common source of confusion when porting or reading older code.
Solutions / Resolution
- Treat -110 as the expected, normal exit condition for a sequential scan — write the retrieval loop to check for it explicitly and exit cleanly, without logging it as an error or raising an alert.
- Reposition before reading further, if more reads are needed after reaching -110 — use
ISFIRST,ISLAST, or a keyedISCURR/isstart()call rather than continuing to callisread(ISNEXT)/isread(ISPREV)against a cursor that's already at the end. - For ESQL/C or SQL-facing code, rely on the standard NOTFOUND condition
(
sqlca.sqlcode == 100) as the primary "no more rows" signal — don't add separate handling for an ISAM-level -110 on top of it unless the code is calling the ISAM API directly. - If -110 arrives earlier than expected, don't assume the retrieval loop is broken — verify
independently how much data should actually be there (a
COUNT(*), or reviewing the key range and starting position) before debugging the loop itself. - Keep monitoring/alerting scoped to genuinely unexpected
iserrnovalues (locking, corruption, argument errors) — instrumenting on -110 itself just produces noise for an entirely ordinary condition.
Examples
The correct sequential-scan loop
int rc;
while ((rc = isread(fd, &record, ISNEXT)) == 0) {
process(&record);
}
if (rc < 0 && iserrno != -110) {
/* a real error — -110 alone means "reached the end", not a failure */
handle_error(iserrno);
}
-110 here is the loop's normal exit path, not a branch that needs error handling of its own.
The bug: reading past the end without repositioning
isread(fd, &record, ISNEXT); /* eventually returns -110 */
isread(fd, &record, ISNEXT); /* still -110 — the cursor never moved */
isread(fd, &record, ISNEXT); /* still -110 */
If more reads are genuinely needed, reposition first:
isread(fd, &record, ISFIRST); /* back to the start, only if that's actually the intent */
Confusing SQL NOTFOUND with a separate ISAM condition
EXEC SQL FETCH cur1 INTO :rec;
if (sqlca.sqlcode == 100) {
/* NOTFOUND — the correct, standard signal at end of result set */
} else if (sqlca.sqlcode < 0) {
/* a real error */
}
/* No separate check against iserrno == -110 needed here — the SQL
layer's own NOTFOUND already covers this for a FETCH loop */
Diagnostic Checks
- Confirm whether -110 arrived at an expected point — compare the number of rows actually
processed before hitting -110 against an independent count:
SELECT COUNT(*) FROM customer WHERE <the same conditions the scan used>; - Review the retrieval loop's exit logic — does it distinguish -110 from genuine errors, or does it lump every negative return into one error path (which would misreport ordinary end-of- scan as a failure)?
- For an unexpectedly early -110, check the key range and starting position used by
isstart()/the initialisread()call — a narrower-than-intended range or an unexpected starting point produces a shorter scan than assumed, not a bug in reading itself. - For code that appears to hang or loop indefinitely, check whether it correctly detects and
exits on -110 rather than repeatedly calling
isread()past the end (Reasons #3).
Related Errors / Related Topics
- -100 — "ISAM error: duplicate value for a record with unique key." The other foundational ISAM-level error in this family, though unrelated in cause — grouped here as background on how this error class is organized.
Unlike most of this range, -110 is not something to "fix" when it appears — confirm it's arriving at the expected point in a scan, and make sure the code treats it as the normal termination signal it is.