From f1da675ba6dadb39ab5c6e5e109e17dfaee84c68 Mon Sep 17 00:00:00 2001 From: zerone0x Date: Fri, 27 Mar 2026 23:42:00 +0800 Subject: [PATCH] fix: detect and rebuild better-sqlite3 on Node.js ABI mismatch The postinstall script only checked whether the native binding file existed on disk. After a Node.js version update, the .node binary can still be present but compiled against a different ABI, causing a MODULE_VERSION mismatch at load time. This adds a runtime load check so the script automatically triggers `npm rebuild better-sqlite3` when the existing binary is incompatible with the running Node.js. Closes #1343 Co-Authored-By: Claude Opus 4.6 --- .../scripts/postinstall.cjs | 36 ++++++++++++++++--- 1 file changed, 31 insertions(+), 5 deletions(-) diff --git a/apps/memos-local-openclaw/scripts/postinstall.cjs b/apps/memos-local-openclaw/scripts/postinstall.cjs index b6593f9ea..361b69c0a 100644 --- a/apps/memos-local-openclaw/scripts/postinstall.cjs +++ b/apps/memos-local-openclaw/scripts/postinstall.cjs @@ -226,7 +226,35 @@ function sqliteBindingsExist() { return false; } -if (sqliteBindingsExist()) { +/** + * Check whether better-sqlite3 can actually be loaded by the current + * Node.js runtime. A binding file may exist on disk but still fail + * with NODE_MODULE_VERSION mismatch after a Node.js or plugin update. + */ +function sqliteLoadsSuccessfully() { + try { + require(path.join(sqliteModulePath, "lib", "index.js")); + return true; + } catch (e) { + if (e && e.message && e.message.includes("NODE_MODULE_VERSION")) { + warn("ABI version mismatch — native module was built for a different Node.js version."); + return false; + } + // For any other load error fall through to the rebuild path as well. + return false; + } +} + +let needsRebuild = false; + +if (!sqliteBindingsExist()) { + warn("better-sqlite3 native bindings not found in plugin dir."); + log(`Searched in: ${DIM}${sqliteModulePath}/build/${RESET}`); + needsRebuild = true; +} else if (!sqliteLoadsSuccessfully()) { + log("Native binding file exists but cannot be loaded by current Node.js."); + needsRebuild = true; +} else { ok("better-sqlite3 is ready."); console.log(` ${GREEN}${BOLD} ┌──────────────────────────────────────────────────┐ @@ -237,12 +265,10 @@ ${GREEN}${BOLD} ┌──────────────────── └──────────────────────────────────────────────────┘${RESET} `); process.exit(0); -} else { - warn("better-sqlite3 native bindings not found in plugin dir."); - log(`Searched in: ${DIM}${sqliteModulePath}/build/${RESET}`); - log("Running: npm rebuild better-sqlite3 (may take 30-60s)..."); } +log("Running: npm rebuild better-sqlite3 (may take 30-60s)..."); + const startMs = Date.now(); const result = spawnSync("npm", ["rebuild", "better-sqlite3"], {