tursodatabase/turso · error · Exception

jsContextPointer == 0

Error message

jsContextPointer == 0

What it means

TursoBridge.install() attaches the native sync engine to the React Native JS runtime by passing the runtime's raw JSI context pointer into installNativeJsi(). It throws this bare Exception when context.getJavaScriptContextHolder().get() returns 0, meaning the bridge saw no live JavaScriptCore/JSI runtime to install into. Without a valid pointer the native side cannot be initialized, so the library refuses rather than crashing the process later.

Solutions

  1. Trigger install only after the JS runtime exists: call it from JS through a native-module method invoked at app entry, or from onCatalystInstanceInitialized(), never from the module constructor.
  2. If you are on Expo, switch to a development build (expo run:android) - Expo Go cannot host custom JSI natives.
  3. After upgrading the turso/sync packages, do a full clean rebuild (cd android && ./gradlew clean, then rebuild) so native and JS sides match.
  4. On the New Architecture, load the module through the TurboModule/interop layer for your RN version and update to a bridge version that supports bridgeless mode.

Example fix

// before
public TurboTursoModule(ReactApplicationContext ctx) {
  bridge.install(ctx); // JS runtime not live yet -> jsContextPointer == 0
}

// after: install lazily, the first time JS asks for it
private boolean installed = false;

@ReactMethod
public void install() throws Exception {
  if (installed) return;
  bridge.install(getReactApplicationContext()); // runtime is live now
  installed = true;
}
Defensive patterns

Strategy: validation

Validate before calling

ReactContext ctx = ...;
JavaScriptContextHolder holder = ctx.getJavaScriptContextHolder();
if (holder == null || holder.get() == 0) {
  // JS runtime not up yet: wait for onCatalystInstanceInitialized / a JS-side signal
  return;
}
bridge.install(ctx);

Try / catch

try {
  bridge.install(reactContext);
} catch (Exception e) {
  Log.w("TursoBridge", "JSI install deferred: " + e.getMessage());
  // schedule one retry once the runtime signals readiness; do not loop blindly
}

Prevention

When it happens

Trigger: Calling install(reactContext) before the Catalyst instance / JS runtime is up (e.g., in the module constructor or too early in onHostResume); running under a runtime that exposes no JS context (Expo Go, remote JS debugger, or an RN build without JSI support); calling install after invalidate() tore the runtime down.

Common situations: Enabling React Native's New Architecture / bridgeless mode where getJavaScriptContextHolder() is empty; using Expo Go, which forbids custom JSI native modules; upgrading the turso npm package without rebuilding the Android app so the native library and JS runtime mismatch; calling install from a background thread before onCatalystInstanceInitialized.

Related errors


AI-assisted analysis of tursodatabase/turso@244cde92a7 (2026-08-20). Data as JSON: /api/errors/15cf1d92e1444c22. Report an issue: GitHub.

Appendix: source

Thrown at bindings/react-native/android/src/main/java/com/turso/sync/reactnative/TursoBridge.java:29

  public static TursoBridge getInstance() {
    return instance;
  }

  private TursoBridge() {
  }

  private native void installNativeJsi(
      long jsContextNativePointer,
      CallInvokerHolderImpl jsCallInvokerHolder,
      String dbPath);

  private native void clearStateNativeJsi();

  public void install(ReactContext context) throws Exception {
    long jsContextPointer = context.getJavaScriptContextHolder().get();
    if (jsContextPointer == 0) {
      throw new Exception("jsContextPointer == 0");
    }
    CallInvokerHolderImpl jsCallInvokerHolder = (CallInvokerHolderImpl) context.getCatalystInstance()
        .getJSCallInvokerHolder();

    // getDatabasePath(...) returns file path - so we pass dummy value and remove it
    // after to get directory path
    String dbPath = context.getDatabasePath("tursoDatabaseFile").getAbsolutePath().replace("tursoDatabaseFile", "");

    installNativeJsi(jsContextPointer, jsCallInvokerHolder, dbPath);
  }

  public void invalidate() {
    clearStateNativeJsi();
  }
}

View on GitHub (pinned to 244cde92a7)