Informix Error -113
-113 ISAM error: the file is locked.
Another user request has opened the file (table) that was requested in exclusive mode. In systems that use files for locking, a tablename.lok file exists. Possibly such a file was left behind when another program terminated abnormally. If you are sure that is the case, you can release the lock by emptying that file. Lock files are not used in many systems, and they are never used with IBM Informix Dynamic Server or IBM Informix OnLine Dynamic Server.
This error occurs with IBM Informix Dynamic Server or IBM Informix OnLine Dynamic Server when a user attempts to access a table that has been locked.
For C-ISAM programs, rerun the program after the file is unlocked. For SQL products, tables are locked explicitly using the LOCK TABLE statement and implicitly during the execution of the CREATE INDEX or ALTER TABLE statement. Rerun the program or query when the table is unlocked.
If you get this error (-113) when using a transaction isolation mode of REPEATABLE READ or SERIALIZABLE, and if your query did not use an index (and therefore had to use a sequential scan of the entire table), the cause of the error might be that another user had either an exclusive lock or a promotable lock on at least one row in the table. If you are in REPEATABLE READ or SERIALIZABLE mode and your query requires a scan (search) of every single record in the table to find all the records that meet the conditions in the WHERE clause, then the engine will need to lock every record in the table to maintain the repeatability of the read. In practice, rather than locking every single record, the engine will try to lock the entire table. But if there are any exclusive locks, or even promotable locks, on any row in the table, then the engine will not be able to get a shared lock on the entire table, and the query will fail.
Oninit® Troubleshooting Guidance
Reasons / Common Causes
-113 is a table-level lock conflict — the file/table itself is locked against your session's request, as opposed to -107's single-row conflict or -106's "needs exclusive access for a structural operation" case. The official text describes three distinct paths to it, worth separating clearly:
- Another session has the table open in exclusive mode.
LOCK TABLE ... IN EXCLUSIVE MODE, an exclusiveDATABASEstatement, or a C-ISAMisopen()withISEXCLLOCKall hold this kind of lock — while it's held, any other session touching the table gets -113. - A stale
tablename.lokfile after an abnormal program termination, in configurations using file-based ISAM locking. A crash or akill -9can leave the lock file behind even though no live process actually holds the lock it represents — subsequent opens see the table as locked when, in reality, nothing is using it anymore. REPEATABLE READorSERIALIZABLEisolation performing a full sequential scan. Those isolation levels need a full-table shared lock to guarantee their semantics; if any row in the table already carries an exclusive or "promotable" lock from unrelated activity elsewhere, the engine can't obtain that shared lock and the entire scan fails with -113 — not just a wait on the specific contended row, which is what a less strict isolation level would produce instead.
Solutions / Resolution
- For an active exclusive holder, wait and retry — same pattern as -106/-107. This is usually transient; the exclusivity will end when the holding session finishes.
- For a suspected stale
.lokfile, confirm first that nothing genuinely holds it — check for a live process referencing the file — before removing it manually. Removing a lock file that a live process still legitimately holds reintroduces exactly the corruption risk file locking exists to prevent. - For
REPEATABLE READ/SERIALIZABLE-caused -113, reconsider whether that isolation level is actually needed for the query in question. A less strict level (COMMITTED READ, orCURSOR STABILITYdepending on what the query actually requires) avoids needing a full-table shared lock and won't conflict with row-level locks held elsewhere for unrelated reasons. - Reduce the duration and scope of exclusive table locks used for maintenance — smaller, batched operations or an off-hours maintenance window minimizes the window during which other sessions see -113.
- Make sure crash/session-cleanup actually reclaims locks and lock files after abnormal terminations, so one earlier crash doesn't have a lingering effect on unrelated sessions long after the fact.
- Build retry logic around -113 on read paths affected by the isolation-level scenario, similar to the retry guidance for -106/-107 — most occurrences are transient rather than indicating a real problem.
Examples
An active exclusive holder
-- Session A
LOCK TABLE inventory IN EXCLUSIVE MODE;
-- performing a bulk maintenance operation
-- Session B, at the same time
SELECT * FROM inventory WHERE sku = 'WIDGET-1';
-- -113: inventory is exclusively locked by session A
Retrying session B after session A's maintenance completes and releases the lock succeeds without any code change.
The stale lock file after a crash
$ ls -la /informix/dbspace/customer.lok
-rw-r----- 1 informix informix 0 Sep 20 03:14 customer.lok
# The process that created this lock file crashed hours ago and no
# longer exists, but the file was never cleaned up
$ ps -ef | grep <pid-that-would-have-held-it>
# (no matching process)
Once confirmed genuinely orphaned (see Diagnostic Checks), removing the stale .lok file
restores normal access — but confirm first, every time; don't remove a lock file on assumption
alone.
REPEATABLE READ blocked by an unrelated promotable lock
SET ISOLATION TO REPEATABLE READ;
SELECT * FROM orders; -- full sequential scan, needs a full-table shared lock
-- -113 if any row in orders currently carries an exclusive or
-- promotable lock from other activity, even if that activity has
-- nothing to do with the rows this query actually cares about
-- Compare:
SET ISOLATION TO COMMITTED READ;
SELECT * FROM orders; -- doesn't need the same full-table shared lock; succeeds
The stricter isolation level is what turned an unrelated row-level lock into a whole-table failure — the fix is usually choosing the isolation level the query actually needs, not chasing the specific row that happened to be locked.
Diagnostic Checks
- Check for an active exclusive lock on the table:
onstat -k - For a suspected stale
.lokfile, confirm no live process holds it before removing anything:
An empty result alongside a confirmed-dead originating process is what justifies manual removal — never remove it on the strength of "it's probably stale" alone.lsof /informix/dbspace/<table>.lok - Check the failing query's isolation level:
or review the application'sSELECT DBINFO('isolevel') FROM systables WHERE tabid = 1;SET ISOLATION/SET TRANSACTIONsetting directly, ifREPEATABLE READ/SERIALIZABLEis suspected to be the actual trigger. - Review for crashed or orphaned sessions:
A session shown as gone but with locks or lock files still attributed to it points at incomplete crash cleanup rather than an active, legitimate conflict.onstat -u
Related Errors / Related Topics
- -106 — "ISAM error: non-exclusive access." The mirror case: -106 is your session failing to get exclusive access it needs; -113 is your session being blocked by exclusivity someone else already holds.
- -107 — "ISAM error: record is locked." The row-level sibling — -113 is the same family of conflict scaled up to the whole table.
If -113 recurs regularly and isn't explained by an active exclusive holder, check the isolation level of the failing query first (Reasons #3) before assuming there's a stuck lock to hunt down.