node-sqlite3
node-sqlite3 copied to clipboard
Node-API crash with unhandled promise after SQLITE_CANTOPEN
Issue Summary
The following crash occurs when a promise doesn't resolve and the SQLite file cannot be opened:
- Version 4.2.0 is not affected
- The crash occurs with the path
xxx/x.db
but notx.db
FATAL ERROR: Error::ThrowAsJavaScriptException napi_throw
1: 0x104cb21dc node::Abort() [/Users/dave/.asdf/installs/nodejs/18.11.0/bin/node]
2: 0x104cb22d4 node::OOMErrorHandler(char const*, bool) [/Users/dave/.asdf/installs/nodejs/18.11.0/bin/node]
3: 0x104cb21f4 node::OnFatalError(char const*, char const*) [/Users/dave/.asdf/installs/nodejs/18.11.0/bin/node]
4: 0x104c82d34 napi_open_callback_scope [/Users/dave/.asdf/installs/nodejs/18.11.0/bin/node]
5: 0x113bece9c Napi::Error::Error(napi_env__*, napi_value__*) [<project>/node_modules/sqlite3/lib/binding/napi-v6-darwin-unknown-arm64/node_sqlite3.node]
6: 0x113beaa6c Napi::Error::ThrowAsJavaScriptException() const [<project>/node_modules/sqlite3/lib/binding/napi-v6-darwin-unknown-arm64/node_sqlite3.node]
7: 0x113bec744 Napi::Reference<Napi::Object>::Unref() [<project>/node_modules/sqlite3/lib/binding/napi-v6-darwin-unknown-arm64/node_sqlite3.node]
8: 0x113c050f4 node_sqlite3::Statement::Baton::~Baton() [<project>/node_modules/sqlite3/lib/binding/napi-v6-darwin-unknown-arm64/node_sqlite3.node]
9: 0x113c08028 node_sqlite3::Statement::EachBaton::~EachBaton() [<project>/node_modules/sqlite3/lib/binding/napi-v6-darwin-unknown-arm64/node_sqlite3.node]
10: 0x113bfc830 node_sqlite3::Statement::CleanQueue() [<project>/node_modules/sqlite3/lib/binding/napi-v6-darwin-unknown-arm64/node_sqlite3.node]
11: 0x113c08228 node_sqlite3::Statement::~Statement() [<project>/node_modules/sqlite3/lib/binding/napi-v6-darwin-unknown-arm64/node_sqlite3.node]
12: 0x113c04c70 node_sqlite3::Statement::~Statement() [<project>/node_modules/sqlite3/lib/binding/napi-v6-darwin-unknown-arm64/node_sqlite3.node]
13: 0x113c06da0 Napi::ObjectWrap<node_sqlite3::Statement>::FinalizeCallback(napi_env__*, void*, void*) [<project>/node_modules/sqlite3/lib/binding/napi-v6-darwin-unknown-arm64/node_sqlite3.node]
14: 0x104c8570c void napi_env__::CallIntoModule<void node_napi_env__::CallFinalizer<true>(void (*)(napi_env__*, void*, void*), void*, void*)::'lambda'(napi_env__*)&, void node_napi_env__::CallbackIntoModule<true, void node_napi_env__::CallFinalizer<true>(void (*)(napi_env__*, void*, void*), void*, void*)::'lambda'(napi_env__*)>(void node_napi_env__::CallFinalizer<true>(void (*)(napi_env__*, void*, void*), void*, void*)::'lambda'(napi_env__*)&&)::'lambda'(napi_env__*, v8::Local<v8::Value>)>(void node_napi_env__::CallFinalizer<true>(void (*)(napi_env__*, void*, void*), void*, void*)::'lambda'(napi_env__*)&, void node_napi_env__::CallFinalizer<true>(void (*)(napi_env__*, void*, void*), void*, void*)::'lambda'(napi_env__*)&&) [/Users/dave/.asdf/installs/nodejs/18.11.0/bin/node]
15: 0x104c8245c void node_napi_env__::CallFinalizer<true>(void (*)(napi_env__*, void*, void*), void*, void*) [/Users/dave/.asdf/installs/nodejs/18.11.0/bin/node]
16: 0x104c6cbb0 v8impl::Reference::Finalize(bool) [/Users/dave/.asdf/installs/nodejs/18.11.0/bin/node]
17: 0x104c82254 node_napi_env__::DeleteMe() [/Users/dave/.asdf/installs/nodejs/18.11.0/bin/node]
18: 0x104c252bc node::CleanupQueue::Drain() [/Users/dave/.asdf/installs/nodejs/18.11.0/bin/node]
19: 0x104c59d8c node::Environment::RunCleanup() [/Users/dave/.asdf/installs/nodejs/18.11.0/bin/node]
20: 0x104c00204 node::FreeEnvironment(node::Environment*) [/Users/dave/.asdf/installs/nodejs/18.11.0/bin/node]
21: 0x104ced124 node::NodeMainInstance::Run() [/Users/dave/.asdf/installs/nodejs/18.11.0/bin/node]
22: 0x104c80ec8 node::LoadSnapshotDataAndRun(node::SnapshotData const**, node::InitializationResult const*) [/Users/dave/.asdf/installs/nodejs/18.11.0/bin/node]
23: 0x104c81190 node::Start(int, char**) [/Users/dave/.asdf/installs/nodejs/18.11.0/bin/node]
24: 0x180fb3e50 start [/usr/lib/dyld]
Steps to Reproduce
- Setup project directory and empty files
mkdir test && cd test
touch index.js
touch index.test.js
- Write to
index.js
andindex.test.js
:
index.js:
const sqlite3 = require('sqlite3').verbose();
const testFunction = () => {
const db = new sqlite3.Database('xxx/x.db');
return new Promise((_resolve, _reject) => {
db.each('SELECT * FROM Files', (_err, _row) => {});
});
}
exports.main = async () => {
await testFunction();
};
index.test.js:
const testFunction = require('./index').main
it('crashes', async () => {
await testFunction();
});
- Run the test
npm i sqlite3 jest-cli
npx jest index.test.js
Version
5.1.2
Node.js Version
18.11.0
How did you install the library?
Via npm on macOS 13.0 Beta (22A5373b) arm64
I also ran into this error, however, it is not a bug. You simply need to handle errors that can occur during database opening by adding a callback to your new sqlite3.Database
constructor and turning it into a promise, like so:
const mode = sqlite3.OPEN_READWRITE | sqlite3.OPEN_FULLMUTEX; // Or whatever you want
const db = await new Promise((resolve, reject) => {
const db_ = new sqlite3.Database('xxx/x.db', mode, err => {
if (err) {
reject(err);
} else {
resolve(db_);
}
});
});
I also handled the error the same way.
The provided example is a contrived example to trigger the issue. It's about the error handling in the C++ code and not the JavaScript code, it shouldn't be possible to raise a Node-API C++ exception from Node.js.
Oh okay, fair enough, I stand corrected 🙂