Which RxStorage are you using?
Premium SQLite storage (rxdb-premium/plugins/storage-sqlite) over expo-sqlite, on React Native + Hermes.
Describe the bug
openSqliteTransaction (plugins/storage-sqlite/sqlite-helpers.js) calls console.dir(err) inside its BEGIN; retry catch handler. console.dir is undefined in a production React Native / Hermes runtime, so the catch handler itself throws TypeError: undefined is not a function.
Two consequences:
- The real SQLite error (
"Database is closed", "API misuse", a transient lock, etc.) is replaced by an opaque TypeError, so the original message/code is lost.
console.dir(err) is evaluated before the retry/terminal decision, so neither branch is reached — transient errors are never retried via promiseWait(0), and terminal errors are never rethrown with their real message. Every transaction-open failure becomes a hard throw.
Offending code
Shipped (minified ESM) form:
export async function openSqliteTransaction(e, r) {
for (var a = !1; !a;)
try {
---
} catch (e) {
console.log("open transaction error (will retry):");
var o = n(e); // errorToPlainJson
if (console.log(o), console.dir(e), // <-- console.dir is undefined in prod Hermes -> throws here
e.message && (e.message.includes("Database is closed") || e.message.includes("API misuse")))
throw e;
await t(0) // promiseWait — unreachable on any error path
}
}
Root cause
React Native's console polyfill (@react-native/js-polyfills/console.js) only provides console.dir under __DEV__. In the production path (the global.nativeLoggingHook branch that always runs in a release build) the console object defines log/info/warn/error/trace/debug/table/group/groupEnd/groupCollapsed/assert/time/count but not dir — dir/dirxml/clear/profile/profileEnd are only restored from the original console inside the if (__DEV__ && originalConsole) block. So console.dir === undefined in every RN/Hermes production build (iOS and Android).
Expected behavior
A failing BEGIN; is logged, then either retried (transient) or rethrown with its original error ("Database is closed" / "API misuse").
Actual behavior
The catch handler throws TypeError: undefined is not a function from console.dir, masking the real error and bypassing the retry/rethrow logic entirely.
Minimal reproduction
Run any rxdb-premium SQLite-storage app on React Native / Hermes in a release build (__DEV__ === false) and force a BEGIN; failure (e.g. close the underlying DB handle mid-write). Observed result: TypeError: undefined is not a function originating from openSqliteTransaction, rather than the underlying SQLite error, and the transaction is not retried.
Versions
rxdb / rxdb-premium: 17.3.0
- React Native: 0.83.6
- Hermes: 0.14.1
Which RxStorage are you using?
Premium SQLite storage (
rxdb-premium/plugins/storage-sqlite) overexpo-sqlite, on React Native + Hermes.Describe the bug
openSqliteTransaction(plugins/storage-sqlite/sqlite-helpers.js) callsconsole.dir(err)inside itsBEGIN;retry catch handler.console.dirisundefinedin a production React Native / Hermes runtime, so the catch handler itself throwsTypeError: undefined is not a function.Two consequences:
"Database is closed","API misuse", a transient lock, etc.) is replaced by an opaqueTypeError, so the original message/code is lost.console.dir(err)is evaluated before the retry/terminal decision, so neither branch is reached — transient errors are never retried viapromiseWait(0), and terminal errors are never rethrown with their real message. Every transaction-open failure becomes a hard throw.Offending code
Shipped (minified ESM) form:
Root cause
React Native's console polyfill (
@react-native/js-polyfills/console.js) only providesconsole.dirunder__DEV__. In the production path (theglobal.nativeLoggingHookbranch that always runs in a release build) the console object defineslog/info/warn/error/trace/debug/table/group/groupEnd/groupCollapsed/assert/time/countbut notdir—dir/dirxml/clear/profile/profileEndare only restored from the original console inside theif (__DEV__ && originalConsole)block. Soconsole.dir === undefinedin every RN/Hermes production build (iOS and Android).Expected behavior
A failing
BEGIN;is logged, then either retried (transient) or rethrown with its original error ("Database is closed"/"API misuse").Actual behavior
The catch handler throws
TypeError: undefined is not a functionfromconsole.dir, masking the real error and bypassing the retry/rethrow logic entirely.Minimal reproduction
Run any rxdb-premium SQLite-storage app on React Native / Hermes in a release build (
__DEV__ === false) and force aBEGIN;failure (e.g. close the underlying DB handle mid-write). Observed result:TypeError: undefined is not a functionoriginating fromopenSqliteTransaction, rather than the underlying SQLite error, and the transaction is not retried.Versions
rxdb/rxdb-premium: 17.3.0