laurent22/joplin · critical
Unable to determine database path.
Error message
Unable to determine database path.
What it means
The React Native database driver can only resolve the SQLite storage directory via platform-specific APIs: RNFS.LibraryDirectoryPath on iOS or a native SystemInformationPackage constant on Android. If neither yields a path, initialization cannot proceed and the driver throws before opening any database.
Solutions
- Rebuild the native app so react-native-fs and SystemInformationPackage are linked (`npx react-native run-android` / clean build).
- Verify NativeModules.SystemInformationPackage is available and exposes databaseDirectory on Android.
- Check Platform.OS handling — the platform must be 'ios' or 'android'; other platforms are unsupported.
- If writing tests, mock the driver/databaseDirectory rather than running this code path.
Example fix
// before (Android: module missing at runtime)
const mod = NativeModules.SystemInformationPackage;
// after
const mod = NativeModules.SystemInformationPackage;
if (!mod?.getConstants?.()?.databaseDirectory) throw new Error('SystemInformationPackage native module not linked — rebuild the app'); Defensive patterns
Strategy: try-catch
Validate before calling
const dir = Platform.OS === 'ios' ? `${RNFS.LibraryDirectoryPath}/LocalDatabase/` : NativeModules.SystemInformationPackage?.getConstants()?.databaseDirectory;
if (!dir) throw new Error('databaseDirectory unavailable — native module not linked'); Type guard
const hasDatabaseDir = (d: string | undefined | null): d is string => typeof d === 'string' && d.length > 0;
Try / catch
try { const db = database(); } catch (e) { if (e.message === 'Unable to determine database path.') throw new Error('Rebuild the app: native modules missing'); else throw e; } Prevention
- Rebuild native binaries after adding/updating react-native packages
- Verify NativeModules.SystemInformationPackage on Android in a debug build
- Run pod install on iOS after dependency changes
When it happens
Trigger: Running on iOS when RNFS.LibraryDirectoryPath is undefined, or on Android when the native module `SystemInformationPackage` (or its databaseDirectory constant) is missing — e.g. native module not linked after adding/upgrading dependencies.
Common situations: Android builds where native autolinking failed or a clean JS-only rebuild was done without re-linking native modules; Expo/managed environments lacking the custom native module; iOS upgrades changing LibraryDirectoryPath semantics.
Understand the failure class
Background: "not installed", "pip install", "required for": how missing-dependency errors surface across open-source libraries — this error's family across 34 libraries.
Related errors
AI-assisted analysis of laurent22/joplin@981a03c5c9 (2026-09-17).
Data as JSON: /api/errors/80b210c8f2854ebc.
Report an issue: GitHub.
Appendix: source
Thrown at packages/app-mobile/utils/database-driver-react-native.ts:17
import * as SQLite from 'expo-sqlite';
import DatabaseDriver, { DatabaseCloseOptions, DatabaseOpenOptions, SqlSelectParams } from '@joplin/lib/database-driver';
import * as RNFS from '@dr.pogodin/react-native-fs';
import { NativeModules, Platform } from 'react-native';
import shim from '@joplin/lib/shim';
import { join } from 'path';
// cspell:ignore NSURLI
const getDatabaseDirectory = async () => {
let databaseDirectory;
if (Platform.OS === 'ios') {
databaseDirectory = `${RNFS.LibraryDirectoryPath}/LocalDatabase/`;
} else if (Platform.OS === 'android') {
databaseDirectory = NativeModules.SystemInformationPackage?.getConstants()?.databaseDirectory;
}
if (!databaseDirectory) throw new Error('Unable to determine database path.');
if (!await shim.fsDriver().exists(databaseDirectory)) {
// For compatibility with react-native-sqlite-storage, exclude the database
// directory from iCloud backups:
await RNFS.mkdir(databaseDirectory, { NSURLIsExcludedFromBackupKey: true });
}
return databaseDirectory;
};
export default class DatabaseDriverReactNative implements DatabaseDriver {
private lastInsertId_: string;
private db_: SQLite.SQLiteDatabase;
public constructor() {
this.lastInsertId_ = null;
}
public async open(options: DatabaseOpenOptions) {
const database = await SQLite.openDatabaseAsync(View on GitHub (pinned to 981a03c5c9)