Informix Error -102
-102 ISAM error: illegal argument to ISAM function.
A parameter that was presented to one of the C-ISAM functions is outside the range of acceptable values. For C-ISAM programs, review the parameters that were used in this function call, and compare them to the documentation for the function. If the error recurs, refer to the information on trapping errors in your Administrator's Guide or Reference to acquire additional diagnostics. Contact IBM Informix Technical Support with the diagnostic information.
Oninit® Troubleshooting Guidance
Reasons / Common Causes
-102 is the ISAM processor's general-purpose parameter-validation failure: some value passed to a C-ISAM function fell outside the range the library will accept. Unlike -100 or -101, which each name a single specific condition, -102 is a catch-all — the official text itself just says a parameter was "outside the range of acceptable values," without saying which parameter or which function. The specific ISAM call that failed (visible in the calling code or a stack trace, not in the error itself) is where the real diagnosis starts.
Realistic causes, roughly in order of how often each turns out to be it:
- An out-of-range or unrecognized mode flag passed to
isopen()/isbuild()— a flag value the library version in use doesn't define, or a combination of flags that individually are valid but together aren't (for example, mixing an exclusive-access mode with a mode that implies shared access). - A record buffer or key-value pointer that's
NULL, uninitialized, or the wrong size — passed toisread(),iswrite(),isrewrite(),isstart(), or similar. The ISAM library validates what it can about the pointer's use (length, alignment implied by the file's own record definition) even though it can't validate the pointer's own validity in the way a memory-safe language would. - A record length passed to
iswrite()/isrewrite()that doesn't match the lengthisbuild()established when the file was created — including an accidental zero or negative length from an uninitialized or miscalculated size variable upstream. - An invalid key number passed to
isstart()or a keyedisread()— referencing a key position that doesn't exist in the file's index descriptor, often from an off-by-one when key numbers are zero-indexed in the API but the calling code assumed 1-indexed, or vice versa. - A hand-constructed or corrupted
keydescstructure — the descriptor for a key has hard limits (at most 8 parts, at most 120 characters total, as-103's own official text spells out), and akeydescbuilt incorrectly, or corrupted by an unrelated memory bug elsewhere in the program, fails validation here rather than at the more specific-103. - Library/header version skew — code compiled against one C-ISAM header's flag definitions, linked at runtime against a different library version, so a flag value that used to be legal is now out of range (or a newly-added flag value the older header doesn't define gets passed through uninitialized).
- A locking or access-mode argument incompatible with how the file is currently open — requesting a lock mode or exclusivity level that conflicts with the mode the file was opened under earlier in the same process.
Solutions / Resolution
- Identify the exact failing call and its arguments first — -102's official text doesn't name the parameter or function, so nothing else here is actionable until you know which ISAM call raised it. Add argument logging immediately before the suspect call if it isn't already there.
- Check every argument against the C-ISAM function reference for the library version actually linked, not just the version the code was originally written against — range and flag legality can change between versions.
- Validate buffers and lengths at the call site: confirm record buffers are allocated to
exactly the length
isbuild()defined for the file, and that length variables passed toiswrite()/isrewrite()are never zero, negative, or derived from an uninitialized value. - Audit
keydescconstruction — prefer building it through a single, tested helper rather than repeating inline field assignments at each call site, and add an assertion on part count and total length before ever passing it toisbuild()/isstart(). - After any C-ISAM library or Informix client SDK upgrade, check the release notes for changed flag values or newly-restricted argument ranges before assuming existing code is unaffected — this is a common trigger for -102 appearing in previously-stable code.
- Confirm header/library consistency across the build — mismatched compile-time headers and runtime library versions is a frequent, hard-to-spot cause; verify both come from the same SDK/version install rather than being picked up from different paths.
- If the failing call is internal to the SQL engine (no application-level ISAM call in the picture), this is an engine-internal condition rather than something application code caused — capture the statement and version information and open a case with IBM Informix Technical Support rather than searching application code for a bug that isn't there.
Examples
The off-by-one key number
/* Index has keys numbered 0..2 in the keydesc array (3 keys total) */
if (isstart(fd, &keydesc, 3, &startkey, ISGREATEQ) < 0) {
/* keydesc index 3 doesn't exist — valid range is 0..2 — -102 */
}
The count of keys (3) and the highest legal key number (2) are easy to conflate — this is one of the most common single-character bugs behind -102.
The stale record length
struct customer_rec rec;
int reclen = 0; /* never actually set before the write */
if (iswrite(fd, &rec) < 0) {
/* if the underlying implementation validates a length argument
derived from a variable like this one, a leftover zero here
is exactly the kind of "argument outside acceptable range"
-102 reports */
}
The bug is upstream of the ISAM call itself — a length or size variable that was supposed to be computed or assigned earlier in the function never was.
Version skew after an upgrade
/* Compiled against an older isam.h where ISEXCLLOCK didn't exist;
the constant 0x40 meant something else in that header. After
linking against an upgraded C-ISAM library at runtime, the same
literal value now collides with a newly-defined flag. */
isopen(fname, ISINPUT | 0x40); /* -102 against the new library */
Using named constants from the header actually linked, rather than literal values carried over from an old build, avoids this class of failure entirely.
Diagnostic Checks
- Log the exact function name and argument values immediately before the failing call, if this isn't already instrumented — this is the single highest-value step, since -102 alone doesn't identify either.
- Compare the linked library version against the headers the program was compiled with:
and check the installed SDK/library version against what the build environment used.ldd <program> | grep -i isam - For a suspected
keydescproblem, dump the structure's part count and total length just before theisbuild()/isstart()call and confirm both are within the documented limits (at most 8 parts, at most 120 characters). - For a suspected record-length problem, compare the length passed to
iswrite()/isrewrite()against the length used in the originalisbuild()call for that file. - Check recent change history — a library upgrade, an OS patch that replaced a shared library, or a recent code change touching the failing call site — anything that shifted timing close to when -102 started appearing.
Related Errors / Related Topics
- -100 — "ISAM error: duplicate value for a record with unique key." Reached through the same ISAM API surface; useful background on how this error family is split between SQL-visible and ISAM-only manifestations.
- -103 — "ISAM error: illegal key descriptor (too many parts or too long)." The specific, named case of an illegal argument when the argument in question is the key descriptor — -102 is the general condition, -103 is called out separately because it's common enough (and diagnosable enough, given the fixed 8-part/120-character limits) to warrant its own code.
If you're chasing -102 with no obvious argument-validation bug in application code, check whether the failing call is internal to the SQL engine rather than something your own program issued — that shifts this from an application bug hunt to an engine-support case.