Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 31 additions & 5 deletions apps/memos-local-openclaw/scripts/postinstall.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Copy link

Copilot AI Mar 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sqliteLoadsSuccessfully() intentionally suppresses all non-ABI load errors. That makes failures like missing DLLs / wrong arch / missing dependency harder to diagnose. Consider logging (at least a truncated) e.message when the error is not a NODE_MODULE_VERSION mismatch so users have actionable context before the rebuild attempt.

Suggested change
// For any other load error fall through to the rebuild path as well.
// For any other load error, log a truncated message so users have context
// before we fall through to the rebuild path.
const rawMsg = e && e.message ? String(e.message) : String(e);
const truncatedMsg = rawMsg.length > 300 ? rawMsg.slice(0, 297) + "..." : rawMsg;
warn(`better-sqlite3 failed to load; will attempt to rebuild. Error: ${truncatedMsg}`);

Copilot uses AI. Check for mistakes.
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;
Comment on lines +248 to +256
Copy link

Copilot AI Mar 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

needsRebuild is set in multiple branches but never read; as written the script rebuilds whenever it doesn't process.exit(0). Remove the variable or use it to explicitly gate the rebuild step to avoid dead code/confusion.

Suggested change
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;
if (!sqliteBindingsExist()) {
warn("better-sqlite3 native bindings not found in plugin dir.");
log(`Searched in: ${DIM}${sqliteModulePath}/build/${RESET}`);
} else if (!sqliteLoadsSuccessfully()) {
log("Native binding file exists but cannot be loaded by current Node.js.");

Copilot uses AI. Check for mistakes.
} else {
Comment on lines +254 to +257
Copy link

Copilot AI Mar 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that the script distinguishes “binding exists” vs “binding loads”, the post-rebuild success path should also validate loadability (not just file existence). Otherwise npm rebuild could succeed and produce a .node file that still fails to load (ABI mismatch persists, wrong prebuild selected, missing runtime dependency), and the script would report success anyway.

Copilot uses AI. Check for mistakes.
ok("better-sqlite3 is ready.");
console.log(`
${GREEN}${BOLD} ┌──────────────────────────────────────────────────┐
Expand All @@ -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"], {
Expand Down
Loading