tursodatabase/turso · critical · Error

@tursodatabase/sync-react-native: Native module not found…

Error message

@tursodatabase/sync-react-native: Native module not found. Make sure you have properly linked the library.
- iOS: Run 'pod install' in your ios directory
- Android: Make sure the package is properly included in your MainApplication.java

What it means

The package's module-init code reads NativeModules.Turso and throws immediately at import time if it is undefined. This means React Native autolinking never registered the native Turso module in the app binary, so there is nothing for the JS side to talk to. It is a build/linking problem, not a runtime logic error.

Solutions

  1. iOS: run cd ios && pod install, then do a full rebuild (xcodebuild / run from Xcode) - a Metro reload is not enough
  2. Expo: switch to a development build (npx expo prebuild, npx expo run:ios / eas build) - the module cannot load inside Expo Go
  3. Android: verify the package appears in the autolinked packages list (npx react-native config) and rebuild; for manual linking, ensure the package is registered in MainApplication
  4. In Jest, map '@tursodatabase/sync-react-native' to a mock in moduleNameMapper so the import-time check never runs
  5. On web/Node targets, import the web/serverless entry instead of the react-native one

Example fix

// jest.config.js - before: tests crash at import with 'Native module not found'
// after: mock the native module in the Jest environment
module.exports = {
  moduleNameMapper: {
    '^@tursodatabase/sync-react-native$': '<rootDir>/__mocks__/turso-rn.ts',
  },
};
Defensive patterns

Strategy: validation

Validate before calling

// Probe before importing the SDK (e.g. in Jest, web, or mixed-platform code)
import { NativeModules, Platform } from 'react-native';
const nativeReady = Platform.OS === 'ios' || Platform.OS === 'android'
  ? !!NativeModules.Turso
  : false;
if (!nativeReady) {
  throw new Error('Turso native module unavailable on this platform - use the web/serverless build or a dev build');
}
const { connect } = await import('@tursodatabase/sync-react-native');

Type guard

function hasTursoNative(mods: Record<string, unknown>): boolean {
  return typeof mods.Turso === 'object' && mods.Turso !== null;
}

Try / catch

Because the throw happens at module import time, wrap a dynamic import: try { turso = await import('@tursodatabase/sync-react-native'); } catch (e) { if (String(e.message).includes('Native module not found')) { /* fall back to web build / skip feature */ } else throw e; }

Prevention

When it happens

Trigger: Any import of '@tursodatabase/sync-react-native' in an app where the native module is absent: iOS without pod install, an Expo Go session (Expo Go cannot load third-party native modules), an Android build where the package is missing from MainApplication/getPackages, or a non-RN runtime (web, Node, Jest) that resolves the RN entry anyway.

Common situations: Fresh clone where a teammate forgot pod install; using Expo Go instead of a dev build or eas build; upgrading RN or switching to Expo modules autolinking silently dropping the package; Jest unit tests importing app code that transitively loads the SDK.

Related errors


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

Appendix: source

Thrown at bindings/react-native/src/index.ts:54

  // Enums
  TursoStatus,
  TursoType,
} from './types';

// Re-export classes
export { Database } from './Database';
export { Statement } from './Statement';

// Export file system configuration function
export { setFileSystemImpl } from './internal/ioProcessor';

// Get the native module
const TursoNative: TursoNativeModule | undefined = NativeModules.Turso;

// Check if native module is available
if (!TursoNative) {
  throw new Error(
    `@tursodatabase/sync-react-native: Native module not found. Make sure you have properly linked the library.\n` +
    `- iOS: Run 'pod install' in your ios directory\n` +
    `- Android: Make sure the package is properly included in your MainApplication.java`
  );
}

// Install the JSI bindings
const installed = TursoNative.install();
if (!installed) {
  throw new Error(
    '@tursodatabase/sync-react-native: Failed to install JSI bindings. Make sure the New Architecture is enabled.'
  );
}

// Get the proxy that was installed on the global object
// __TursoProxy is declared globally in types.ts
const TursoProxy: TursoProxyType = __TursoProxy;

View on GitHub (pinned to 244cde92a7)