Node + tsx “__name is not a function” 當機
摘要
透過 Node 搭配 tsx 執行 OpenClaw 時,啟動階段就會失敗:
[openclaw] Failed to start CLI: TypeError: __name is not a function
at createSubsystemLogger (.../src/logging/subsystem.ts:203:25)
at .../src/agents/auth-profiles/constants.ts:25:20
這個問題在開發腳本從 Bun 切換到 tsx 之後出現(commit 2871657e,2026-01-06)。相同的執行路徑在 Bun 下運作正常。
環境
- Node:v25.x(在 v25.3.0 上觀察到)
- tsx:4.21.0
- OS:macOS(其他執行 Node 25 的平台也可能重現)
重現步驟(僅限 Node)
# 在 repo 根目錄
node --version
pnpm install
node --import tsx src/entry.ts status
在 repo 中的最小重現
node --import tsx scripts/repro/tsx-name-repro.ts
Node 版本檢查
- Node 25.3.0:失敗
- Node 22.22.0(Homebrew
node@22):失敗 - Node 24:尚未安裝;需要驗證
筆記 / 假說
tsx使用 esbuild 轉換 TS/ESM。esbuild 的keepNames會產生__name輔助函式,並將函式定義包裝為__name(...)。- 當機訊息顯示
__name存在但在執行期間不是函式,這表示在 Node 25 的載入器路徑中,該輔助函式遺失或被覆寫了。 - 類似的
__name輔助函式問題在其他 esbuild 使用者中也有報告,通常是輔助函式遺失或被重寫所致。
迴歸歷史
2871657e(2026-01-06):腳本從 Bun 改為 tsx,讓 Bun 變成選用。- 在此之前(Bun 路徑),
openclaw status和gateway:watch都正常運作。
解決方法
-
開發腳本改回使用 Bun(目前的暫時回退)。
-
使用 Node + tsc watch,然後執行編譯後的產出:
pnpm exec tsc --watch --preserveWatchOutput node --watch openclaw.mjs status -
已在本機確認:
pnpm exec tsc -p tsconfig.json+node openclaw.mjs status在 Node 25 上正常運作。 -
如果可以的話,在 TS 載入器中停用 esbuild keepNames(防止
__name輔助函式注入);tsx 目前不提供此選項。 -
在 Node LTS(22/24)上測試
tsx,確認是否為 Node 25 特有的問題。
參考資料
- https://opennext.js.org/cloudflare/howtos/keep_names
- https://esbuild.github.io/api/#keep-names
- https://github.com/evanw/esbuild/issues/1031
後續步驟
- 在 Node 22/24 上重現以確認是否為 Node 25 迴歸。
- 測試
tsx的 nightly 版本,或在已知迴歸存在時固定到較早版本。 - 如果在 Node LTS 上也能重現,向上游提交包含
__name堆疊追蹤的最小重現。