Title: node:sqlite segfaults when db.close() is called from a user-defined function callback during query execution · Issue #63180 · nodejs/node · GitHub
Open Graph Title: node:sqlite segfaults when db.close() is called from a user-defined function callback during query execution · Issue #63180 · nodejs/node
X Title: node:sqlite segfaults when db.close() is called from a user-defined function callback during query execution · Issue #63180 · nodejs/node
Description: Version all current versions (tested v22.22.2, v24.15.0, v25.9.0, and v26.1.0) Platform All platforms are impacted. (but because you asked:) $ uname -a Linux swift 6.17.0-23-generic #23~24.04.1-Ubuntu SMP PREEMPT_DYNAMIC Tue Apr 14 16:11...
Open Graph Description: Version all current versions (tested v22.22.2, v24.15.0, v25.9.0, and v26.1.0) Platform All platforms are impacted. (but because you asked:) $ uname -a Linux swift 6.17.0-23-generic #23~24.04.1-Ubu...
X Description: Version all current versions (tested v22.22.2, v24.15.0, v25.9.0, and v26.1.0) Platform All platforms are impacted. (but because you asked:) $ uname -a Linux swift 6.17.0-23-generic #23~24.04.1-Ubu...
Opengraph URL: https://github.com/nodejs/node/issues/63180
X: @github
Domain: github.com
{"@context":"https://schema.org","@type":"DiscussionForumPosting","headline":"node:sqlite segfaults when db.close() is called from a user-defined function callback during query execution","articleBody":"### Version\n\nall current versions (tested v22.22.2, v24.15.0, v25.9.0, and v26.1.0)\n\n### Platform\n\n```text\nAll platforms are impacted.\n\n(but because you asked:)\n\n$ uname -a\nLinux swift 6.17.0-23-generic #23~24.04.1-Ubuntu SMP PREEMPT_DYNAMIC Tue Apr 14 16:11:48 UTC 2 x86_64 x86_64 x86_64 GNU/Linux\n$ cat /etc/lsb-release \nDISTRIB_ID=Ubuntu\nDISTRIB_RELEASE=24.04\nDISTRIB_CODENAME=noble\nDISTRIB_DESCRIPTION=\"Ubuntu 24.04.4 LTS\"\n```\n\n### Subsystem\n\nsqlite\n\n### What steps will reproduce the bug?\n\nThere are **two distinct crash classes**, both triggered by `db.close()` from inside a user-defined function callback. The original `.all()` repro and the `.run()` repro below are verified to segfault on `main`; the other Class A variants are expected to segfault by code inspection — they all funnel through the same `StatementExecutionHelper` step sites.\n\n**Class A — Statement VM freed mid-step.** The original report; affects every StatementSync execution path that runs `sqlite3_step`:\n\n```js\n// .all() — segfaults\nconst { DatabaseSync } = require(\"node:sqlite\");\nconst db = new DatabaseSync(\":memory:\");\ndb.exec(\"CREATE TABLE t (id INTEGER PRIMARY KEY, v INTEGER)\");\ndb.prepare(\"INSERT INTO t VALUES (1, 10)\").run();\ndb.prepare(\"INSERT INTO t VALUES (2, 20)\").run();\ndb.function(\"close_db\", (x) => { try { db.close(); } catch {} return x; });\ndb.prepare(\"SELECT close_db(v) FROM t\").all();\n```\n\n```js\n// .get() — same crash\ndb.prepare(\"SELECT close_db(v) FROM t\").get();\n```\n\n```js\n// iterator — same crash\nconst iter = db.prepare(\"SELECT close_db(v) FROM t\").iterate();\niter.next();\n```\n\n```js\n// SQL tag store .all() / .get() — same crash\nconst sql = db.createTagStore(4);\nsql.all`SELECT close_db(v) FROM t`;\n```\n\n**Class B — `db->Connection()` null deref after step.** Distinct crash path, only surfaces in `.run()` (and the SQL-tag `.run()`), even after Class A is fixed by deferring finalize. After `sqlite3_step` returns, `StatementExecutionHelper::Run` reads `sqlite3_last_insert_rowid(db->Connection())` and `sqlite3_changes64(db->Connection())`. The reentrant `db.close()` set `db->connection_ = nullptr` before step returned, and the bundled SQLite is built without `SQLITE_ENABLE_API_ARMOR`, so passing `NULL` to those calls is a null-pointer deref:\n\n```js\n// .run() — segfaults via the connection-null path\nconst { DatabaseSync } = require(\"node:sqlite\");\nconst db = new DatabaseSync(\":memory:\");\ndb.exec(\"CREATE TABLE t (id INTEGER PRIMARY KEY, v INTEGER)\");\ndb.function(\"close_db\", (x) => { try { db.close(); } catch {} return x; });\ndb.prepare(\"INSERT INTO t SELECT close_db(1), close_db(2)\").run();\n```\n\n```js\n// SQL tag store .run() — same crash\nconst sql = db.createTagStore(4);\nsql.run`INSERT INTO t SELECT close_db(${1}), close_db(${2})`;\n```\n\n### How often does it reproduce? Is there a required condition?\n\n100%.\n\nThe user-function callback must call db.close() while the outer sqlite3_step is still on the call stack.\n\n### What is the expected behavior? Why is that the expected behavior?\n\nEither a clean error (\"database closed during query\" / SQLITE_INTERRUPT-style) or graceful completion of the in-flight statement followed by close. Process must not crash.\n\n### What do you see instead?\n\nSegmentation fault (core dumped), exit code 139 on linux\n\n### Additional information\n\n(full disclosure: produced with assistance from claude) ","author":{"url":"https://github.com/mceachen","@type":"Person","name":"mceachen"},"datePublished":"2026-05-08T00:27:57Z","url":"https://github.com/nodejs/node/issues/63180"}
| react-profiling | 0 |
| react-import-map | react,react-dom,react-dom/client,react-dom/profiling,react-is,react-reconciler,react/compiler-runtime,react/jsx-dev-runtime,react/jsx-runtime,scheduler@d5750093facf |
| route-pattern | /_view_fragments/issues/show/:user_id/:repository/:id/issue_layout(.:format) |
| route-controller | voltron_issues_fragments |
| route-action | issue_layout |
| fetch-nonce | v2:f411655d-9bae-1b8d-1d9c-2a388bccad1d |
| current-catalog-service-hash | 81bb79d38c15960b92d99bca9288a9108c7a47b18f2423d0f6438c5b7bcd2114 |
| request-id | EE12:32DB95:637239:86993D:6AED2446 |
| html-safe-nonce | 4ed2d8472d0125ea210ff1d9dc635c82ee31a9784ff2d5830e12646acb3b7c7a |
| visitor-payload | eyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiJFRTEyOjMyREI5NTo2MzcyMzk6ODY5OTNEOjZBRUQyNDQ2IiwidmlzaXRvcl9pZCI6IjMyMDA4OTY3MTQ5NzcxMjU0NDYiLCJyZWdpb25fZWRnZSI6ImlhZCIsInJlZ2lvbl9yZW5kZXIiOiJpYWQifQ== |
| visitor-hmac | dd5f95aa65eb77e3e3bcb11f19cc1c850f3929d7c50205c82ec30f23916bfee2 |
| hovercard-subject-tag | issue:4402844769 |
| github-keyboard-shortcuts | repository,issues,copilot |
| google-site-verification | Apib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I |
| octolytics-url | https://collector.github.com/github/collect |
| analytics-location | / |
| fb:app_id | 1401488693436528 |
| apple-itunes-app | app-id=1477376905, app-argument=https://github.com/_view_fragments/issues/show/nodejs/node/63180/issue_layout |
| twitter:image | https://opengraph.githubassets.com/abf92feb08154a77d5f97bb729ca945e35c9cba21986438ae93fa99694a64604/nodejs/node/issues/63180 |
| twitter:card | summary_large_image |
| og:image | https://opengraph.githubassets.com/abf92feb08154a77d5f97bb729ca945e35c9cba21986438ae93fa99694a64604/nodejs/node/issues/63180 |
| og:image:alt | Version all current versions (tested v22.22.2, v24.15.0, v25.9.0, and v26.1.0) Platform All platforms are impacted. (but because you asked:) $ uname -a Linux swift 6.17.0-23-generic #23~24.04.1-Ubu... |
| og:image:width | 1200 |
| og:image:height | 600 |
| og:site_name | GitHub |
| og:type | object |
| og:author:username | mceachen |
| hostname | github.com |
| expected-hostname | github.com |
| None | e3e0f7f63e50c6fe879198a93a0a023a648ecc0a5e9bc3b5e033ac57172237e6 |
| turbo-cache-control | no-preview |
| go-import | github.com/nodejs/node git https://github.com/nodejs/node.git |
| octolytics-dimension-user_id | 9950313 |
| octolytics-dimension-user_login | nodejs |
| octolytics-dimension-repository_id | 27193779 |
| octolytics-dimension-repository_nwo | nodejs/node |
| octolytics-dimension-repository_public | true |
| octolytics-dimension-repository_is_fork | false |
| octolytics-dimension-repository_network_root_id | 27193779 |
| octolytics-dimension-repository_network_root_nwo | nodejs/node |
| turbo-body-classes | logged-out env-production page-responsive |
| disable-turbo | false |
| browser-stats-url | https://api.github.com/_private/browser/stats |
| browser-errors-url | https://api.github.com/_private/browser/errors |
| release | 707a24b346ac8a82878b9c084efaa38a997660cb |
| ui-target | full |
| theme-color | #1e2327 |
| color-scheme | light dark |
| react-app-name | issues |
Links:
Viewport: width=device-width