diff --git a/packages/loot-core/src/platform/server/sqlite/index.electron.ts b/packages/loot-core/src/platform/server/sqlite/index.electron.ts
index 74c2b7dd188dcd04470f871a7d0c370ae011d5d6..2a479e4f943fe68be1a2e5f6e9ffe30f5bb5e9ce 100644
--- a/packages/loot-core/src/platform/server/sqlite/index.electron.ts
+++ b/packages/loot-core/src/platform/server/sqlite/index.electron.ts
@@ -99,7 +99,7 @@ export async function asyncTransaction(
 }
 
 function regexp(regex: string, text: string | null) {
-  return new RegExp(regex).test(text) ? 1 : 0;
+  return new RegExp(regex).test(text || '') ? 1 : 0;
 }
 
 export function openDatabase(pathOrBuffer: string | Buffer) {
diff --git a/packages/loot-core/src/platform/server/sqlite/index.web.test.ts b/packages/loot-core/src/platform/server/sqlite/index.web.test.ts
index 0d21e18d8b1951d763bd80a2d30b0ba2c3770025..de8102cc96e4134bb7fe0d1cb6bd817ad3263a2a 100644
--- a/packages/loot-core/src/platform/server/sqlite/index.web.test.ts
+++ b/packages/loot-core/src/platform/server/sqlite/index.web.test.ts
@@ -16,6 +16,7 @@ beforeAll(() => {
 
 const initSQL = `
 CREATE TABLE numbers (id TEXT PRIMARY KEY, number INTEGER);
+CREATE TABLE textstrings (id TEXT PRIMARY KEY, string TEXT);
 `;
 
 describe('Web sqlite', () => {
@@ -85,4 +86,25 @@ describe('Web sqlite', () => {
     // @ts-expect-error Property 'number' does not exist on type 'unknown'
     expect(rows[2].number).toBe(6);
   });
+
+  it('should match regex on text fields', async () => {
+    const db = await openDatabase();
+    execQuery(db, initSQL);
+
+    runQuery(
+      db,
+      "INSERT INTO textstrings (id, string) VALUES ('id1', 'not empty string')",
+    );
+    runQuery(db, "INSERT INTO textstrings (id) VALUES ('id2')");
+
+    const rows = runQuery(
+      db,
+      'SELECT id FROM textstrings where REGEXP("n.", string)',
+      null,
+      true,
+    );
+    expect(rows.length).toBe(1);
+    // @ts-expect-error Property 'id' does not exist on type 'unknown'
+    expect(rows[0].id).toBe('id1');
+  });
 });
diff --git a/packages/loot-core/src/platform/server/sqlite/index.web.ts b/packages/loot-core/src/platform/server/sqlite/index.web.ts
index f8f91b7a41a718080d9cfdc3905de2f5fc7552e4..64670e879f63ffe3a51330cd19accb0f7547feb9 100644
--- a/packages/loot-core/src/platform/server/sqlite/index.web.ts
+++ b/packages/loot-core/src/platform/server/sqlite/index.web.ts
@@ -159,7 +159,7 @@ export async function asyncTransaction(db: Database, fn: () => Promise<void>) {
 }
 
 function regexp(regex: string, text: string) {
-  return new RegExp(regex).test(text) ? 1 : 0;
+  return new RegExp(regex).test(text || '') ? 1 : 0;
 }
 
 export async function openDatabase(pathOrBuffer?: string | Buffer) {
diff --git a/upcoming-release-notes/3480.md b/upcoming-release-notes/3480.md
new file mode 100644
index 0000000000000000000000000000000000000000..212a45746793d706b14cc87d7eab3bf11715d2e0
--- /dev/null
+++ b/upcoming-release-notes/3480.md
@@ -0,0 +1,6 @@
+---
+category: Bugfix
+authors: [qedi-r]
+---
+
+Fix 'matches' operator incorrectly matching empty strings.