Pre-submission checklist | 提交前检查
Bug Description | 问题描述
✓ Lockfile passes supply-chain policies (verified 11h ago)
Progress: resolved 1, reused 0, downloaded 0, added 0
[WARN] 3 deprecated subdependencies found: boolean@3.2.0, ini@1.3.0, prebuild-install@7.1.3
[WARN] Issues with peer dependencies found. Run "pnpm peers check" to list them.
dependencies:
- @memtensor/memos-local-plugin ^2.0.20
Packages: -51
Progress: resolved 154, reused 51, downloaded 0, added 0, done
node_modules/protobufjs postinstall$ node scripts/postinstall
node_modules/onnxruntime-node postinstall$ node ./script/install
node_modules/esbuild postinstall$ node install.js
node_modules/sharp install$ node install/check.js || npm run build
node_modules/better-sqlite3 install$ prebuild-install || node-gyp rebuild --release
node_modules/protobufjs postinstall: Done
node_modules/sharp install: Done
node_modules/better-sqlite3 install: (node:259528) [DEP0176] DeprecationWarning: fs.R_OK is deprecated, use fs.constants.R_OK instead
node_modules/better-sqlite3 install: (Use DeepSeek Harness --trace-deprecation ... to show where the warning was created)
node_modules/onnxruntime-node postinstall: Done
node_modules/esbuild postinstall: Done
node_modules/better-sqlite3 install: prebuild-install warn install No prebuilt binaries found (target=24.18.1 runtime=node arch=x64 libc= platform=win32)
node_modules/better-sqlite3 install: C:\Users\Administrator.dsh\profiles\desktop\node_modules\better-sqlite3>if not defined npm_config_node_gyp (node "D:\AI\DeepSeek-Harness\resources\runtime\pnpm\dist\node-gyp-bin\..\node_modules\node-gyp\bin\node-gyp.js" rebuild --release ) else (node "D:\AI\DeepSeek-Harness\resources\runtime\pnpm\dist\node_modules\node-gyp\bin\node-gyp.js" rebuild --release )
node_modules/better-sqlite3 install: gyp info it worked if it ends with ok
node_modules/better-sqlite3 install: gyp info using node-gyp@12.4.0
node_modules/better-sqlite3 install: gyp info using node@24.18.1 | win32 | x64
node_modules/better-sqlite3 install: gyp info find Python using Python version 3.12.5 found at "D:\DevKit\Python\Python312\python.exe"
node_modules/better-sqlite3 install: gyp info find VS using VS2022 (17.14.37531.7) found at:
node_modules/better-sqlite3 install: gyp info find VS "C:\Program Files\Microsoft Visual Studio\2022\Community"
node_modules/better-sqlite3 install: gyp info find VS run with --verbose for detailed information
node_modules/better-sqlite3 install: gyp info spawn D:\DevKit\Python\Python312\python.exe
node_modules/better-sqlite3 install: gyp info spawn args [
node_modules/better-sqlite3 install: gyp info spawn args 'D:\AI\DeepSeek-Harness\resources\runtime\pnpm\dist\node_modules\node-gyp\gyp\gyp_main.py',
node_modules/better-sqlite3 install: gyp info spawn args 'binding.gyp',
node_modules/better-sqlite3 install: gyp info spawn args '-f',
node_modules/better-sqlite3 install: gyp info spawn args 'msvs',
node_modules/better-sqlite3 install: gyp info spawn args '-I',
node_modules/better-sqlite3 install: gyp info spawn args 'C:\Users\Administrator\.dsh\profiles\desktop\node_modules\better-sqlite3\build\config.gypi',
node_modules/better-sqlite3 install: gyp info spawn args '-I',
node_modules/better-sqlite3 install: gyp info spawn args 'D:\AI\DeepSeek-Harness\resources\runtime\pnpm\dist\node_modules\node-gyp\addon.gypi',
node_modules/better-sqlite3 install: gyp info spawn args '-I',
node_modules/better-sqlite3 install: gyp info spawn args 'C:\Users\Administrator\AppData\Local\node-gyp\Cache\24.18.1\include\node\common.gypi',
node_modules/better-sqlite3 install: gyp info spawn args '-Dlibrary=shared_library',
node_modules/better-sqlite3 install: gyp info spawn args '-Dvisibility=default',
node_modules/better-sqlite3 install: gyp info spawn args '-Dnode_root_dir=C:\Users\Administrator\AppData\Local\node-gyp\Cache\24.18.1',
node_modules/better-sqlite3 install: gyp info spawn args '-Dnode_gyp_dir=D:\AI\DeepSeek-Harness\resources\runtime\pnpm\dist\node_modules\node-gyp',
node_modules/better-sqlite3 install: gyp info spawn args '-Dnode_lib_file=C:\\Users\\Administrator\\AppData\\Local\\node-gyp\\Cache\\24.18.1\\<(target_arch)\\node.lib',
node_modules/better-sqlite3 install: gyp info spawn args '-Dmodule_root_dir=C:\Users\Administrator\.dsh\profiles\desktop\node_modules\better-sqlite3',
node_modules/better-sqlite3 install: gyp info spawn args '-Dnode_engine=v8',
node_modules/better-sqlite3 install: gyp info spawn args '--depth=.',
node_modules/better-sqlite3 install: gyp info spawn args '--no-parallel',
node_modules/better-sqlite3 install: gyp info spawn args '--generator-output',
node_modules/better-sqlite3 install: gyp info spawn args 'C:\Users\Administrator\.dsh\profiles\desktop\node_modules\better-sqlite3\build',
node_modules/better-sqlite3 install: gyp info spawn args '-Goutput_dir=.'
node_modules/better-sqlite3 install: gyp info spawn args ]
node_modules/better-sqlite3 install: gyp: name 'enable_thin_lto' is not defined while evaluating condition 'enable_thin_lto=="true"' in binding.gyp while trying to load binding.gyp
node_modules/better-sqlite3 install: gyp ERR! configure error
node_modules/better-sqlite3 install: gyp ERR! stack Error: gyp failed with exit code: 1
node_modules/better-sqlite3 install: gyp ERR! stack at ChildProcess. (D:\AI\DeepSeek-Harness\resources\runtime\pnpm\dist\node_modules\node-gyp\lib\configure.js:317:18)
node_modules/better-sqlite3 install: gyp ERR! stack at ChildProcess.emit (node:events:509:28)
node_modules/better-sqlite3 install: gyp ERR! stack at ChildProcess._handle.onexit (node:internal/child_process:295:12)
node_modules/better-sqlite3 install: gyp ERR! System Windows_NT 10.0.26200
node_modules/better-sqlite3 install: gyp ERR! command "D:\AI\DeepSeek-Harness\DeepSeek Harness.exe" "D:\AI\DeepSeek-Harness\resources\runtime\pnpm\dist\node_modules\node-gyp\bin\node-gyp.js" "rebuild" "--release"
node_modules/better-sqlite3 install: gyp ERR! cwd C:\Users\Administrator.dsh\profiles\desktop\node_modules\better-sqlite3
node_modules/better-sqlite3 install: gyp ERR! node -v v24.18.1
node_modules/better-sqlite3 install: gyp ERR! node-gyp -v v12.4.0
node_modules/better-sqlite3 install: gyp ERR! $npm_package_name better-sqlite3
node_modules/better-sqlite3 install: gyp ERR! $npm_package_version 12.11.1
node_modules/better-sqlite3 install: gyp ERR! not ok
node_modules/better-sqlite3 install: Failed
[ELIFECYCLE] Command failed with exit code 1.
How to Reproduce | 如何重现
Environment | 环境信息
deepseek harness desktop:V0.2.0-rc.2
Additional Context | 其他信息
No response
Willingness to Implement | 实现意愿
Root cause analysis (appended after triage)
TL;DR — This is not a bug in MemOS's own code. It happens in the native-dependency build path of @memtensor/memos-local-plugin when that build runs inside the DeepSeek Harness Electron runtime: better-sqlite3 finds no prebuilt binary, falls back to a source build, and node-gyp then aborts because the gyp config it generates carries Electron's build variables — which have no enable_thin_lto key — while Node 24.18.1's common.gypi unconditionally reads that variable on Windows. There is a second, independent blocker behind it (ABI 137 vs 149), so silencing the gyp error alone is not enough.
Environment (measured on the reporting machine, read-only)
| Component |
Value |
| DSH desktop |
0.2.0-rc.2 |
| Runtime that runs pnpm/node-gyp |
DeepSeek Harness.exe = Electron 44.0.0 (via ELECTRON_RUN_AS_NODE) |
| Node / ABI |
node 24.18.1, process.versions.modules = 149, napi 10, sqlite 3.53.1 |
| pnpm / node-gyp |
pnpm 11.7.0, node-gyp 12.4.0 |
| Packages involved |
@memtensor/memos-local-plugin@2.0.20 → better-sqlite3@12.11.1, prebuild-install@7.1.3, node-abi@3.96.0 |
| Native toolchain present |
Python 3.12.5, Visual Studio 2022 17.14 — so this is not a missing-compiler problem |
Step 1 — no prebuilt binary is found
better-sqlite3's install script is prebuild-install || node-gyp rebuild --release. prebuild-install@7.1.3 defaults to runtime = 'node' and target = process.versions.node (24.18.1), then asks node-abi for the ABI. node-abi@3.96.0 short-circuits:
if (runtime === 'node') {
if (!target) return process.versions.modules
if (target === process.versions.node) return process.versions.modules
}
Inside the Electron process this returns 149 (Electron's ABI) instead of Node 24's 137, so it requests an asset named ...-node-v149-win32-x64, which cannot exist → No prebuilt binaries found (target=24.18.1 runtime=node arch=x64 libc= platform=win32). This cannot be worked around with flags as long as the runtime is Electron: prebuild-install recomputes the ABI unconditionally, and every target equal to process.versions.node resolves to Electron's ABI.
Step 2 — the source build fails (the reported error)
node-gyp 12.4.0 then runs in that same Electron process. It downloads the Node 24.18.1 headers and passes -I ...\include\node\common.gypi, but since neither --nodedir nor --dist-url is set, create-config-gypi.js falls back to process.config, so the generated build/config.gypi contains Electron's build variables:
| Variable |
generated build/config.gypi (Electron) |
headers include/node/config.gypi (Node 24.18.1) |
enable_lto |
"true" |
"false" |
enable_thin_lto |
absent |
"false" |
v8_enable_pointer_compression |
1 |
0 |
v8_enable_sandbox |
1 |
0 |
node_module_version |
149 |
137 |
Node 24.18.1's common.gypi (Windows branch, evaluated while the file is loaded) contains both LTO conditions:
['enable_lto=="true"', { ... }],
['enable_thin_lto=="true"', { ... }],
gyp requires any variable used in a condition to be defined; an undefined variable is a hard error, not false:
gyp: name 'enable_thin_lto' is not defined while evaluating condition
'enable_thin_lto=="true"' in binding.gyp while trying to load binding.gyp
The in binding.gyp part is only gyp's attribution to the build file being loaded — the condition itself lives in Node's common.gypi, which every binding.gyp pulls in via -I. better-sqlite3's own binding.gyp contains no thin_lto reference (verified), so there is nothing to patch there either.
This is invisible in normal Node usage for two reasons: a real Node binary's process.config.variables does define enable_thin_lto, and when --nodedir/--dist-url is passed node-gyp reads the headers' config.gypi, which also defines it. Related upstream report on the same variable, in a different failure mode (thin-LTO flags leaking into an MSVC project, not an undefined variable): nodejs/node#64674. The same failure shape applies to any node-gyp-built native dependency installed through DSH desktop, not just this one.
Step 3 — even a successful compile would not load
better-sqlite3 is a V8-ABI addon (NODE_MODULE_INIT, so it registers as node_register_module_v137 with these headers), while the DSH host process requires ABI 149. If gyp were fixed without changing the headers, require('better-sqlite3') would still fail with the usual "compiled against a different Node.js version" error. Only a build against the Electron 44 headers can load in this host.
Result on disk
pnpm exits with [ELIFECYCLE] Command failed with exit code 1 and rolls the install back: the profile package.json and pnpm-lock.yaml have no @memtensor entry, while leftovers remain (empty node_modules/@memtensor/, half-written node_modules/better-sqlite3/build/config.gypi). An earlier attempt of the same install stopped one step before this, at [ERR_PNPM_IGNORED_BUILDS] — pnpm does not run dependency build scripts until they are approved, and approving them is what exposes this failure.
Possible directions (not validated end-to-end here)
Plugin / package side:
- Do not depend on compiling a V8-ABI addon on the client: ship prebuilt binaries per platform/ABI (Electron 44 → ABI 149), or make the prebuild lookup runtime-aware.
- Or switch the local storage layer to something ABI-stable: a Node-API module, or
node:sqlite — the DSH Electron 44 runtime embeds Node 24.18.1 with SQLite (process.versions.sqlite = 3.53.1).
Client / install side (the actual fix for DSH desktop):
- Install profile dependencies with Electron headers, i.e. electron-rebuild semantics:
npm_config_runtime=electron, npm_config_target=44.0.0, npm_config_disturl=https://electronjs.org/headers. node-gyp then reads the Electron headers' config.gypi (which defines enable_thin_lto) and produces ABI-149 binaries.
Minimal unblock for the gyp error only (does not fix the ABI mismatch):
- Set
npm_config_nodedir=<node-gyp cache>\24.18.1 or npm_config_disturl=https://nodejs.org/download/release/, so create-config-gypi.js reads the Node headers' config.gypi, which has enable_thin_lto: "false".
How this was determined
Read-only inspection on the reporting machine, without modifying the plugin: the DSH profile (package.json, pnpm-lock.yaml, .plugin-manager/logs/operation-*/pnpm.log), the installed better-sqlite3/binding.gyp and generated build/config.gypi, prebuild-install/rc.js, node-abi/index.js, node-gyp's create-config-gypi.js, and Node 24.18.1's cached common.gypi / config.gypi; plus running ELECTRON_RUN_AS_NODE=1 "DeepSeek Harness.exe" -e "..." to print process.versions and process.config.variables — which reports enable_lto: true and confirms the enable_thin_lto key is absent.
中文摘要
根因:不是 MemOS 自身代码的问题,而是插件的原生依赖在 DSH 桌面端的 Electron 运行时里编译不了。
@memtensor/memos-local-plugin@2.0.20 依赖 better-sqlite3@12.11.1;DSH 用自带的 Electron(DeepSeek Harness.exe,Electron 44.0.0 / 内嵌 Node 24.18.1 / ABI 149)充当 Node 来跑 pnpm 和 node-gyp。
- 预编译包没命中:
prebuild-install 默认 runtime=node、target=24.18.1,而 node-abi 有个快捷分支 —— target === process.versions.node 时直接返回 process.versions.modules,在 Electron 进程里是 149(Node 24 实际是 137),于是它去找根本不存在的 node-v149 产物。
- 源码编译报错的原因:node-gyp 没收到
--nodedir/--dist-url,生成的 build/config.gypi 取的是 Electron 的 process.config —— 有 enable_lto: "true",但完全没有 enable_thin_lto 这个键;而 Node 24.18.1 的 common.gypi 在 Windows 分支上会直接判断 enable_thin_lto=="true",gyp 要求条件变量必须已定义,未定义就直接 fatal 退出。报错里的 "in binding.gyp" 只是 gyp 对当前加载文件的归属描述(common.gypi 是通过 -I 被包含进来的),better-sqlite3 自己的 binding.gyp 里没有 thin_lto。
- 还有第二层问题:即便编译通过,产物是按 Node 24.18.1 头文件(ABI 137)编译的,宿主 Electron 44 需要 149,
require() 仍会报 ABI 不匹配,必须用 Electron 头文件编译才能真正加载。
- 结果:pnpm 以 ELIFECYCLE 退出并回滚(profile 的
package.json/pnpm-lock.yaml 里已没有 @memtensor,只留下空目录和半成品的 build 目录);再往前一次尝试是卡在 ERR_PNPM_IGNORED_BUILDS(pnpm 需先批准依赖的构建脚本),批准后才暴露出这个编译失败。
修复建议:插件侧最好别依赖客户端源码编译(按 ABI 提供预编译产物,或改用 Node-API / node:sqlite);DSH 侧安装 profile 依赖时应按 electron-rebuild 的方式带 npm_config_runtime=electron、npm_config_target=44.0.0、npm_config_disturl=https://electronjs.org/headers。只绕过 gyp 报错(不解决 ABI)可传 npm_config_nodedir/npm_config_disturl,让 node-gyp 读 Node 头文件里那份定义了 enable_thin_lto: "false" 的 config.gypi。
Related issues and an upstream fix (update)
Duplicate check
Searched this repo and GitHub-wide for the error in this report — there is no exact duplicate: this is currently the only issue carrying enable_thin_lto is not defined / ELIFECYCLE for a DSH desktop plugin install. What exists instead is a recurring family of better-sqlite3 native-module reports, all from other clients or other Node majors, and all closed:
| Issue |
State |
Why it is not a duplicate |
| #1734 |
CLOSED/COMPLETED |
better-sqlite3 ABI mismatch on Node 25; fixed by upgrading better-sqlite3 to 12.10.0 so that Node 25 prebuilds exist. Here the version is already 12.11.1, and the ABI is resolved from Electron (149), so upgrading the package alone cannot help. |
| #1343 |
CLOSED/COMPLETED |
Windows ABI mismatch, manual rebuild required; fixed by #2049, released in v2.0.23. |
| #1296 |
CLOSED/NOT_PLANNED |
Windows first-start missing binding; auto-closed for inactivity. |
| #1258, #1201, #1192, #1358, #1199 |
CLOSED |
Could not locate the bindings file / Windows path resolution — same loading stage, different cause. |
| #1639 |
CLOSED |
Memory Viewer not starting on Node 24 — again a Node-major change breaking the native module. |
| #2160 |
OPEN |
Viewer fails to start on Ubuntu 24.04 + Hermes; its better-sqlite3 rebuild succeeds, so the root cause differs — but the "broken semi-installed state, needs manual cleaning up" it reports matches the rollback leftovers described above, so the two are worth cross-referencing. |
| #2437, #2405, #2407 |
OPEN |
Also DSH desktop, but unrelated defects (aborted turns, session format v4). |
| #1545 |
CLOSED |
npm install -g answered 404 because the package was not published to npm yet — unrelated. |
Upstream, only nodejs/node#64674 mentions the same gyp variable — a different failure mode (thin-LTO flags leaking into an MSVC project → LNK1117, not an undefined variable); closed 2026-07-22.
Cleaner fix for the gyp error: node-gyp >= 13.0.0
nodejs/node-gyp#3331 ("fix: disable LTO for addon builds on Windows", merged 2026-06-10, first released in v13.0.0 on 2026-06-12) added this to lib/create-config-gypi.js:
// disable LTO for addon builds. node release builds may enable (thin) LTO,
variables.enable_lto = 'false'
variables.enable_thin_lto = 'false'
With node-gyp >= 13.0.0 the generated build/config.gypi therefore always defines enable_thin_lto, and the failure reported here cannot occur. DSH desktop bundles node-gyp 12.4.0 (released 2026-06-05), whose create-config-gypi.js contains no such lines — it misses the fix by seven days. Upgrading the bundled node-gyp to >= 13 is thus the most direct client-side remedy, and it supersedes the npm_config_nodedir / npm_config_disturl workaround suggested above. Neither of them fixes the ABI mismatch in Step 3, which still requires Electron headers.
中文摘要
重复性排查:全站搜索后确认——没有重复 issue。#2439 是目前唯一带 enable_thin_lto is not defined / ELIFECYCLE 报错的 issue;仓库里只有一批 better-sqlite3 原生模块的"家族史":#1734(Node 25 ABI 不匹配,靠升级 better-sqlite3 到 12.10.0 修好)、#1343(Windows ABI,由 #2049 修复并在 v2.0.23 发布)、#1296(Windows 缺 binding,无响应被自动关闭)、#1258/#1201/#1192/#1358/#1199(bindings 找不到 / Windows 路径解析)、#1639(Node 24 上 viewer 不启动)。其中 #2160 仍处于打开状态(Ubuntu/Hermes,rebuild 成功但 viewer 起不来),根因不同,但它描述的"半安装残留、需要手动清理"与本 issue 的回滚残留一致,值得互引。DSH 相关的 #2437/#2405/#2407 是别的问题;#1545 是当年包还没上 npm 的 404。上游只有 nodejs/node#64674 提到同一变量,但那是另一种失效模式(thin-LTO 参数注入 MSVC 工程导致 LNK1117),已于 2026-07-22 关闭。
更干净的修法:node-gyp ≥ 13.0.0(nodejs/node-gyp#3331,2026-06-10 合并,v13.0.0 于 2026-06-12 发布)在 lib/create-config-gypi.js 里显式写死 variables.enable_lto = 'false'、variables.enable_thin_lto = 'false',因此升级后生成的 build/config.gypi 一定带这个变量,本 issue 的报错不会再出现。DSH 内置的是 node-gyp 12.4.0(2026-06-05 发布),差 7 天没吃到这个修复。这是客户端侧最直接的解法,比正文里 npm_config_nodedir/disturl 的绕法更干净;不过两者都不解决第 3 步的 ABI 137/149 不匹配,那一层仍必须用 Electron 头文件编译。
Pre-submission checklist | 提交前检查
Bug Description | 问题描述
✓ Lockfile passes supply-chain policies (verified 11h ago)
Progress: resolved 1, reused 0, downloaded 0, added 0
[WARN] 3 deprecated subdependencies found: boolean@3.2.0, ini@1.3.0, prebuild-install@7.1.3
[WARN] Issues with peer dependencies found. Run "pnpm peers check" to list them.
dependencies:
Packages: -51
Progress: resolved 154, reused 51, downloaded 0, added 0, done
node_modules/protobufjs postinstall$ node scripts/postinstall
node_modules/onnxruntime-node postinstall$ node ./script/install
node_modules/esbuild postinstall$ node install.js
node_modules/sharp install$ node install/check.js || npm run build
node_modules/better-sqlite3 install$ prebuild-install || node-gyp rebuild --release
node_modules/protobufjs postinstall: Done
node_modules/sharp install: Done
node_modules/better-sqlite3 install: (node:259528) [DEP0176] DeprecationWarning: fs.R_OK is deprecated, use fs.constants.R_OK instead
node_modules/better-sqlite3 install: (Use
DeepSeek Harness --trace-deprecation ...to show where the warning was created)node_modules/onnxruntime-node postinstall: Done
node_modules/esbuild postinstall: Done
node_modules/better-sqlite3 install: prebuild-install warn install No prebuilt binaries found (target=24.18.1 runtime=node arch=x64 libc= platform=win32)
node_modules/better-sqlite3 install: C:\Users\Administrator.dsh\profiles\desktop\node_modules\better-sqlite3>if not defined npm_config_node_gyp (node "D:\AI\DeepSeek-Harness\resources\runtime\pnpm\dist\node-gyp-bin\..\node_modules\node-gyp\bin\node-gyp.js" rebuild --release ) else (node "D:\AI\DeepSeek-Harness\resources\runtime\pnpm\dist\node_modules\node-gyp\bin\node-gyp.js" rebuild --release )
node_modules/better-sqlite3 install: gyp info it worked if it ends with ok
node_modules/better-sqlite3 install: gyp info using node-gyp@12.4.0
node_modules/better-sqlite3 install: gyp info using node@24.18.1 | win32 | x64
node_modules/better-sqlite3 install: gyp info find Python using Python version 3.12.5 found at "D:\DevKit\Python\Python312\python.exe"
node_modules/better-sqlite3 install: gyp info find VS using VS2022 (17.14.37531.7) found at:
node_modules/better-sqlite3 install: gyp info find VS "C:\Program Files\Microsoft Visual Studio\2022\Community"
node_modules/better-sqlite3 install: gyp info find VS run with --verbose for detailed information
node_modules/better-sqlite3 install: gyp info spawn D:\DevKit\Python\Python312\python.exe
node_modules/better-sqlite3 install: gyp info spawn args [
node_modules/better-sqlite3 install: gyp info spawn args 'D:\AI\DeepSeek-Harness\resources\runtime\pnpm\dist\node_modules\node-gyp\gyp\gyp_main.py',
node_modules/better-sqlite3 install: gyp info spawn args 'binding.gyp',
node_modules/better-sqlite3 install: gyp info spawn args '-f',
node_modules/better-sqlite3 install: gyp info spawn args 'msvs',
node_modules/better-sqlite3 install: gyp info spawn args '-I',
node_modules/better-sqlite3 install: gyp info spawn args 'C:\Users\Administrator\.dsh\profiles\desktop\node_modules\better-sqlite3\build\config.gypi',
node_modules/better-sqlite3 install: gyp info spawn args '-I',
node_modules/better-sqlite3 install: gyp info spawn args 'D:\AI\DeepSeek-Harness\resources\runtime\pnpm\dist\node_modules\node-gyp\addon.gypi',
node_modules/better-sqlite3 install: gyp info spawn args '-I',
node_modules/better-sqlite3 install: gyp info spawn args 'C:\Users\Administrator\AppData\Local\node-gyp\Cache\24.18.1\include\node\common.gypi',
node_modules/better-sqlite3 install: gyp info spawn args '-Dlibrary=shared_library',
node_modules/better-sqlite3 install: gyp info spawn args '-Dvisibility=default',
node_modules/better-sqlite3 install: gyp info spawn args '-Dnode_root_dir=C:\Users\Administrator\AppData\Local\node-gyp\Cache\24.18.1',
node_modules/better-sqlite3 install: gyp info spawn args '-Dnode_gyp_dir=D:\AI\DeepSeek-Harness\resources\runtime\pnpm\dist\node_modules\node-gyp',
node_modules/better-sqlite3 install: gyp info spawn args '-Dnode_lib_file=C:\\Users\\Administrator\\AppData\\Local\\node-gyp\\Cache\\24.18.1\\<(target_arch)\\node.lib',
node_modules/better-sqlite3 install: gyp info spawn args '-Dmodule_root_dir=C:\Users\Administrator\.dsh\profiles\desktop\node_modules\better-sqlite3',
node_modules/better-sqlite3 install: gyp info spawn args '-Dnode_engine=v8',
node_modules/better-sqlite3 install: gyp info spawn args '--depth=.',
node_modules/better-sqlite3 install: gyp info spawn args '--no-parallel',
node_modules/better-sqlite3 install: gyp info spawn args '--generator-output',
node_modules/better-sqlite3 install: gyp info spawn args 'C:\Users\Administrator\.dsh\profiles\desktop\node_modules\better-sqlite3\build',
node_modules/better-sqlite3 install: gyp info spawn args '-Goutput_dir=.'
node_modules/better-sqlite3 install: gyp info spawn args ]
node_modules/better-sqlite3 install: gyp: name 'enable_thin_lto' is not defined while evaluating condition 'enable_thin_lto=="true"' in binding.gyp while trying to load binding.gyp
node_modules/better-sqlite3 install: gyp ERR! configure error
node_modules/better-sqlite3 install: gyp ERR! stack Error:
gypfailed with exit code: 1node_modules/better-sqlite3 install: gyp ERR! stack at ChildProcess. (D:\AI\DeepSeek-Harness\resources\runtime\pnpm\dist\node_modules\node-gyp\lib\configure.js:317:18)
node_modules/better-sqlite3 install: gyp ERR! stack at ChildProcess.emit (node:events:509:28)
node_modules/better-sqlite3 install: gyp ERR! stack at ChildProcess._handle.onexit (node:internal/child_process:295:12)
node_modules/better-sqlite3 install: gyp ERR! System Windows_NT 10.0.26200
node_modules/better-sqlite3 install: gyp ERR! command "D:\AI\DeepSeek-Harness\DeepSeek Harness.exe" "D:\AI\DeepSeek-Harness\resources\runtime\pnpm\dist\node_modules\node-gyp\bin\node-gyp.js" "rebuild" "--release"
node_modules/better-sqlite3 install: gyp ERR! cwd C:\Users\Administrator.dsh\profiles\desktop\node_modules\better-sqlite3
node_modules/better-sqlite3 install: gyp ERR! node -v v24.18.1
node_modules/better-sqlite3 install: gyp ERR! node-gyp -v v12.4.0
node_modules/better-sqlite3 install: gyp ERR! $npm_package_name better-sqlite3
node_modules/better-sqlite3 install: gyp ERR! $npm_package_version 12.11.1
node_modules/better-sqlite3 install: gyp ERR! not ok
node_modules/better-sqlite3 install: Failed
[ELIFECYCLE] Command failed with exit code 1.
How to Reproduce | 如何重现
Environment | 环境信息
deepseek harness desktop:V0.2.0-rc.2
Additional Context | 其他信息
No response
Willingness to Implement | 实现意愿
Root cause analysis (appended after triage)
TL;DR — This is not a bug in MemOS's own code. It happens in the native-dependency build path of
@memtensor/memos-local-pluginwhen that build runs inside the DeepSeek Harness Electron runtime:better-sqlite3finds no prebuilt binary, falls back to a source build, and node-gyp then aborts because the gyp config it generates carries Electron's build variables — which have noenable_thin_ltokey — while Node 24.18.1'scommon.gypiunconditionally reads that variable on Windows. There is a second, independent blocker behind it (ABI 137 vs 149), so silencing the gyp error alone is not enough.Environment (measured on the reporting machine, read-only)
DeepSeek Harness.exe= Electron 44.0.0 (viaELECTRON_RUN_AS_NODE)24.18.1,process.versions.modules = 149, napi 10, sqlite 3.53.1@memtensor/memos-local-plugin@2.0.20→better-sqlite3@12.11.1,prebuild-install@7.1.3,node-abi@3.96.0Step 1 — no prebuilt binary is found
better-sqlite3's install script isprebuild-install || node-gyp rebuild --release.prebuild-install@7.1.3defaults toruntime = 'node'andtarget = process.versions.node(24.18.1), then asksnode-abifor the ABI.node-abi@3.96.0short-circuits:Inside the Electron process this returns 149 (Electron's ABI) instead of Node 24's 137, so it requests an asset named
...-node-v149-win32-x64, which cannot exist →No prebuilt binaries found (target=24.18.1 runtime=node arch=x64 libc= platform=win32). This cannot be worked around with flags as long as the runtime is Electron:prebuild-installrecomputes the ABI unconditionally, and every target equal toprocess.versions.noderesolves to Electron's ABI.Step 2 — the source build fails (the reported error)
node-gyp 12.4.0 then runs in that same Electron process. It downloads the Node 24.18.1 headers and passes
-I ...\include\node\common.gypi, but since neither--nodedirnor--dist-urlis set,create-config-gypi.jsfalls back toprocess.config, so the generatedbuild/config.gypicontains Electron's build variables:build/config.gypi(Electron)include/node/config.gypi(Node 24.18.1)enable_lto"true""false"enable_thin_lto"false"v8_enable_pointer_compression10v8_enable_sandbox10node_module_version149137Node 24.18.1's
common.gypi(Windows branch, evaluated while the file is loaded) contains both LTO conditions:gyp requires any variable used in a condition to be defined; an undefined variable is a hard error, not
false:The
in binding.gyppart is only gyp's attribution to the build file being loaded — the condition itself lives in Node'scommon.gypi, which everybinding.gyppulls in via-I.better-sqlite3's ownbinding.gypcontains nothin_ltoreference (verified), so there is nothing to patch there either.This is invisible in normal Node usage for two reasons: a real Node binary's
process.config.variablesdoes defineenable_thin_lto, and when--nodedir/--dist-urlis passed node-gyp reads the headers'config.gypi, which also defines it. Related upstream report on the same variable, in a different failure mode (thin-LTO flags leaking into an MSVC project, not an undefined variable): nodejs/node#64674. The same failure shape applies to any node-gyp-built native dependency installed through DSH desktop, not just this one.Step 3 — even a successful compile would not load
better-sqlite3is a V8-ABI addon (NODE_MODULE_INIT, so it registers asnode_register_module_v137with these headers), while the DSH host process requires ABI 149. If gyp were fixed without changing the headers,require('better-sqlite3')would still fail with the usual "compiled against a different Node.js version" error. Only a build against the Electron 44 headers can load in this host.Result on disk
pnpm exits with
[ELIFECYCLE] Command failed with exit code 1and rolls the install back: the profilepackage.jsonandpnpm-lock.yamlhave no@memtensorentry, while leftovers remain (emptynode_modules/@memtensor/, half-writtennode_modules/better-sqlite3/build/config.gypi). An earlier attempt of the same install stopped one step before this, at[ERR_PNPM_IGNORED_BUILDS]— pnpm does not run dependency build scripts until they are approved, and approving them is what exposes this failure.Possible directions (not validated end-to-end here)
Plugin / package side:
node:sqlite— the DSH Electron 44 runtime embeds Node 24.18.1 with SQLite (process.versions.sqlite = 3.53.1).Client / install side (the actual fix for DSH desktop):
npm_config_runtime=electron,npm_config_target=44.0.0,npm_config_disturl=https://electronjs.org/headers. node-gyp then reads the Electron headers'config.gypi(which definesenable_thin_lto) and produces ABI-149 binaries.Minimal unblock for the gyp error only (does not fix the ABI mismatch):
npm_config_nodedir=<node-gyp cache>\24.18.1ornpm_config_disturl=https://nodejs.org/download/release/, socreate-config-gypi.jsreads the Node headers'config.gypi, which hasenable_thin_lto: "false".How this was determined
Read-only inspection on the reporting machine, without modifying the plugin: the DSH profile (
package.json,pnpm-lock.yaml,.plugin-manager/logs/operation-*/pnpm.log), the installedbetter-sqlite3/binding.gypand generatedbuild/config.gypi,prebuild-install/rc.js,node-abi/index.js, node-gyp'screate-config-gypi.js, and Node 24.18.1's cachedcommon.gypi/config.gypi; plus runningELECTRON_RUN_AS_NODE=1 "DeepSeek Harness.exe" -e "..."to printprocess.versionsandprocess.config.variables— which reportsenable_lto: trueand confirms theenable_thin_ltokey is absent.中文摘要
根因:不是 MemOS 自身代码的问题,而是插件的原生依赖在 DSH 桌面端的 Electron 运行时里编译不了。
@memtensor/memos-local-plugin@2.0.20依赖better-sqlite3@12.11.1;DSH 用自带的 Electron(DeepSeek Harness.exe,Electron 44.0.0 / 内嵌 Node 24.18.1 / ABI 149)充当 Node 来跑 pnpm 和 node-gyp。prebuild-install默认runtime=node、target=24.18.1,而node-abi有个快捷分支 ——target === process.versions.node时直接返回process.versions.modules,在 Electron 进程里是 149(Node 24 实际是 137),于是它去找根本不存在的node-v149产物。--nodedir/--dist-url,生成的build/config.gypi取的是 Electron 的process.config—— 有enable_lto: "true",但完全没有enable_thin_lto这个键;而 Node 24.18.1 的common.gypi在 Windows 分支上会直接判断enable_thin_lto=="true",gyp 要求条件变量必须已定义,未定义就直接 fatal 退出。报错里的 "in binding.gyp" 只是 gyp 对当前加载文件的归属描述(common.gypi是通过-I被包含进来的),better-sqlite3自己的binding.gyp里没有 thin_lto。require()仍会报 ABI 不匹配,必须用 Electron 头文件编译才能真正加载。package.json/pnpm-lock.yaml里已没有@memtensor,只留下空目录和半成品的 build 目录);再往前一次尝试是卡在ERR_PNPM_IGNORED_BUILDS(pnpm 需先批准依赖的构建脚本),批准后才暴露出这个编译失败。修复建议:插件侧最好别依赖客户端源码编译(按 ABI 提供预编译产物,或改用 Node-API /
node:sqlite);DSH 侧安装 profile 依赖时应按 electron-rebuild 的方式带npm_config_runtime=electron、npm_config_target=44.0.0、npm_config_disturl=https://electronjs.org/headers。只绕过 gyp 报错(不解决 ABI)可传npm_config_nodedir/npm_config_disturl,让 node-gyp 读 Node 头文件里那份定义了enable_thin_lto: "false"的config.gypi。Related issues and an upstream fix (update)
Duplicate check
Searched this repo and GitHub-wide for the error in this report — there is no exact duplicate: this is currently the only issue carrying
enable_thin_lto is not defined/ELIFECYCLEfor a DSH desktop plugin install. What exists instead is a recurring family ofbetter-sqlite3native-module reports, all from other clients or other Node majors, and all closed:149), so upgrading the package alone cannot help.Could not locate the bindings file/ Windows path resolution — same loading stage, different cause.better-sqlite3rebuild succeeds, so the root cause differs — but the "broken semi-installed state, needs manual cleaning up" it reports matches the rollback leftovers described above, so the two are worth cross-referencing.npm install -ganswered 404 because the package was not published to npm yet — unrelated.Upstream, only nodejs/node#64674 mentions the same gyp variable — a different failure mode (thin-LTO flags leaking into an MSVC project →
LNK1117, not an undefined variable); closed 2026-07-22.Cleaner fix for the gyp error: node-gyp >= 13.0.0
nodejs/node-gyp#3331 ("fix: disable LTO for addon builds on Windows", merged 2026-06-10, first released in v13.0.0 on 2026-06-12) added this to
lib/create-config-gypi.js:With node-gyp >= 13.0.0 the generated
build/config.gypitherefore always definesenable_thin_lto, and the failure reported here cannot occur. DSH desktop bundles node-gyp 12.4.0 (released 2026-06-05), whosecreate-config-gypi.jscontains no such lines — it misses the fix by seven days. Upgrading the bundled node-gyp to >= 13 is thus the most direct client-side remedy, and it supersedes thenpm_config_nodedir/npm_config_disturlworkaround suggested above. Neither of them fixes the ABI mismatch in Step 3, which still requires Electron headers.中文摘要
重复性排查:全站搜索后确认——没有重复 issue。#2439 是目前唯一带
enable_thin_lto is not defined/ELIFECYCLE报错的 issue;仓库里只有一批better-sqlite3原生模块的"家族史":#1734(Node 25 ABI 不匹配,靠升级 better-sqlite3 到 12.10.0 修好)、#1343(Windows ABI,由 #2049 修复并在 v2.0.23 发布)、#1296(Windows 缺 binding,无响应被自动关闭)、#1258/#1201/#1192/#1358/#1199(bindings 找不到 / Windows 路径解析)、#1639(Node 24 上 viewer 不启动)。其中 #2160 仍处于打开状态(Ubuntu/Hermes,rebuild 成功但 viewer 起不来),根因不同,但它描述的"半安装残留、需要手动清理"与本 issue 的回滚残留一致,值得互引。DSH 相关的 #2437/#2405/#2407 是别的问题;#1545 是当年包还没上 npm 的 404。上游只有 nodejs/node#64674 提到同一变量,但那是另一种失效模式(thin-LTO 参数注入 MSVC 工程导致 LNK1117),已于 2026-07-22 关闭。更干净的修法:node-gyp ≥ 13.0.0(nodejs/node-gyp#3331,2026-06-10 合并,v13.0.0 于 2026-06-12 发布)在
lib/create-config-gypi.js里显式写死variables.enable_lto = 'false'、variables.enable_thin_lto = 'false',因此升级后生成的build/config.gypi一定带这个变量,本 issue 的报错不会再出现。DSH 内置的是 node-gyp 12.4.0(2026-06-05 发布),差 7 天没吃到这个修复。这是客户端侧最直接的解法,比正文里npm_config_nodedir/disturl的绕法更干净;不过两者都不解决第 3 步的 ABI 137/149 不匹配,那一层仍必须用 Electron 头文件编译。