From 927eaf54b97b30173aa82442e3e71b4c675df9a6 Mon Sep 17 00:00:00 2001 From: "Kamat, Trivikram" <16024985+trivikr@users.noreply.github.com> Date: Wed, 29 Jul 2026 08:07:21 -0700 Subject: [PATCH] sqlite: isolate applyChangeset filter errors Track filter callback failures within each applyChangeset() invocation. Returning false from xFilter is not a SQLite error. This previously left the database-wide suppression flag set, which could hide the next unrelated SQLite error. Signed-off-by: Kamat, Trivikram <16024985+trivikr@users.noreply.github.com> Assisted-by: codex:gpt-5.6-sol --- src/node_sqlite.cc | 11 ++++++----- test/parallel/test-sqlite-session.js | 7 +++++++ 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/node_sqlite.cc b/src/node_sqlite.cc index 282184ddcf02d3..dcdbb7874e1202 100644 --- a/src/node_sqlite.cc +++ b/src/node_sqlite.cc @@ -2277,6 +2277,7 @@ void DatabaseSync::ApplyChangeset(const FunctionCallbackInfo& args) { Local conflictFunc; Local filterFunc; + bool filterCallbackFailed = false; if (args.Length() > 1 && !args[1]->IsUndefined()) { if (!args[1]->IsObject()) { THROW_ERR_INVALID_ARG_TYPE(env->isolate(), @@ -2338,25 +2339,25 @@ void DatabaseSync::ApplyChangeset(const FunctionCallbackInfo& args) { filterFunc = filterValue.As(); - context.filterCallback = - [env, db, &filterFunc](std::string_view item) -> bool { + context.filterCallback = [env, &filterFunc, &filterCallbackFailed]( + std::string_view item) -> bool { // If there was an error in the previous call to the filter's // callback, we skip calling it again. - if (db->ignore_next_sqlite_error_) { + if (filterCallbackFailed) { return false; } Local argv[1]; if (!ToV8Value(env->context(), item, env->isolate()) .ToLocal(&argv[0])) { - db->SetIgnoreNextSQLiteError(true); + filterCallbackFailed = true; return false; } Local result; if (!filterFunc->Call(env->context(), Null(env->isolate()), 1, argv) .ToLocal(&result)) { - db->SetIgnoreNextSQLiteError(true); + filterCallbackFailed = true; return false; } diff --git a/test/parallel/test-sqlite-session.js b/test/parallel/test-sqlite-session.js index ad481ba4de77cb..8b65bb1672e663 100644 --- a/test/parallel/test-sqlite-session.js +++ b/test/parallel/test-sqlite-session.js @@ -388,6 +388,13 @@ test('filter handler throws', (t) => { name: 'Error', message: 'Error filtering table data1' }); + + t.assert.throws(() => { + database2.exec('CREATE TABLEEEE'); + }, { + code: 'ERR_SQLITE_ERROR', + message: /syntax error/, + }); }); test('database.createSession() - filter changes', (t) => {