Skip to content

fix: install failed in deepseek harness desktop #2439

Description

@ushaio

Pre-submission checklist | 提交前检查

  • I have searched existing issues and this hasn't been mentioned before | 我已搜索现有问题,确认此问题尚未被提及
  • I have read the project documentation and confirmed this issue doesn't already exist | 我已阅读项目文档并确认此问题尚未存在
  • This issue is specific to MemOS and not a general software issue | 该问题是针对 MemOS 的,而不是一般软件问题

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 | 如何重现

Image Image

Environment | 环境信息

deepseek harness desktop:V0.2.0-rc.2

Additional Context | 其他信息

No response

Willingness to Implement | 实现意愿

  • I'm willing to implement this myself | 我愿意自己解决
  • I would like someone else to implement this | 我希望其他人来解决

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 运行时里编译不了。

  1. @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。
  2. 预编译包没命中:prebuild-install 默认 runtime=node、target=24.18.1,而 node-abi 有个快捷分支 —— target === process.versions.node 时直接返回 process.versions.modules,在 Electron 进程里是 149(Node 24 实际是 137),于是它去找根本不存在的 node-v149 产物。
  3. 源码编译报错的原因: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。
  4. 还有第二层问题:即便编译通过,产物是按 Node 24.18.1 头文件(ABI 137)编译的,宿主 Electron 44 需要 149,require() 仍会报 ABI 不匹配,必须用 Electron 头文件编译才能真正加载。
  5. 结果: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 头文件编译。

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

area:pluginOpenClaw & Hermesstatus:needs-triageNeeds initial triage | 需要初步判断 & 问题复现types:bugSomething isn't working | 功能异常

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions