I'm developing a React Native application using Expo (SDK 51) and SQLite. I've implemented local database operations for managing orders, but I'm encountering a persistent warning about an unhandled promise rejection. Here are the details:
The Issue
On each app refresh, I receive the following warning:
Possible unhandled promise rejection (id: X):
Error: Call to function 'NativeDatabase.execAsync' has been rejected.
-> Caused by: java.lang.NullPointerException: java.lang.NullPointerException
The warning appears continuously, and the id increments each time (e.g., id: 1, id: 2, id: 3, etc.).
My Code
Here's the relevant code for my database operations:
import * as SQLite from 'expo-sqlite';
import { useEffect } from 'react';
async function createLocalDatabase() {
const db = await SQLite.openDatabaseAsync("orders.db");
await db.execAsync(`
PRAGMA journal_mode = WAL;
CREATE TABLE IF NOT EXISTS order_header (
id INTEGER PRIMARY KEY AUTOINCREMENT,
firm TEXT NOT NULL,
shop TEXT NOT NULL,
delivery_date DATE NOT NULL,
notice TEXT,
counterparty_id INTEGER
);
CREATE TABLE IF NOT EXISTS order_items (
id INTEGER PRIMARY KEY AUTOINCREMENT,
item_name TEXT NOT NULL,
sale_unit TEXT NOT NULL,
quantity REAL NOT NULL,
order_header_id INTEGER NOT NULL,
FOREIGN KEY (order_header_id) REFERENCES order_header (id)
);
`);
}
useEffect(() => {
createLocalDatabase();
}, []);
async function insertOrderHeader(db, firm, shop, deliveryDate, notice, counterpartyId) {
const statement = await db.prepareAsync(
"INSERT INTO order_header (firm, shop, delivery_date, notice, counterparty_id) VALUES (?, ?, ?, ?, ?)"
);
try {
const result = await statement.executeAsync([
firm,
shop,
deliveryDate,
notice,
counterpartyId,
]);
return result.lastInsertRowId;
} finally {
await statement.finalizeAsync();
}
}
async function insertOrderItem(
db,
orderHeaderId,
itemName,
saleUnit,
quantity
) {
const statement = await db.prepareAsync(
"INSERT INTO order_items (order_header_id, item_name, sale_unit, quantity) VALUES (?, ?, ?, ?)"
);
try {
await statement.executeAsync([
orderHeaderId,
itemName,
saleUnit,
quantity,
]);
} finally {
await statement.finalizeAsync();
}
}
async function insertOrderWithItems(
firm,
shop,
deliveryDate,
notice,
orderItems
) {
const db = await SQLite.openDatabaseAsync("orders.db");
try {
await db.execAsync("BEGIN TRANSACTION");
const orderHeaderId = await insertOrderHeader(
db,
firm,
shop,
deliveryDate,
notice
);
for (const item of orderItems) {
await insertOrderItem(
db,
orderHeaderId,
item.name,
item.saleUnit,
item.quantity
);
}
await db.execAsync("COMMIT");
console.log(
"Order with items inserted successfully. Order ID:",
orderHeaderId
);
return orderHeaderId;
} catch (error) {
await db.execAsync("ROLLBACK");
console.error("Error inserting order with items:", error);
throw error;
}
}
What I've Tried
Questions
Any insights or suggestions would be greatly appreciated. Thank you!
Environment
Expo ver: ~51.0.18
expo-sqlite version: ~14.0.5
React Native version: 0.74.3
Device: Motorola E20
I had the same issue with the same phone. It seems to be an error from Motorola and how it handles NativeDatabase, because in other devices such as TCL or Samsung this issue doesn't reproduce.
The fix is use a new connection each time you open the database
const db = await SQLite.openDatabaseAsync(databaseFile, {
useNewConnection: true
});