openclaw - 💡(How to fix) Fix Plugin update fails with ERR_MODULE_NOT_FOUND on first openclaw update after new release [2 comments, 3 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#60020Fetched 2026-04-08 02:37:21
View on GitHub
Comments
2
Participants
3
Timeline
2
Reactions
0
Timeline (top)
commented ×2

Running openclaw update after a new release fails to update plugins on the first attempt with:

Failed to update dingtalk: Error [ERR_MODULE_NOT_FOUND]: Cannot find module
'/home/tom/.nvm/versions/node/v22.22.1/lib/node_modules/openclaw/dist/install.runtime-BEOb-kNW.js'
imported from '/home/tom/.nvm/versions/node/v22.22.1/lib/node_modules/openclaw/dist/install-Ca5qyNuE.js'

Running openclaw update a second time succeeds.

Error Message

Failed to update dingtalk: Error [ERR_MODULE_NOT_FOUND]: Cannot find module

Root Cause

The update flow in src/cli/update-cli/update-command.ts runs plugin updates in the same process after replacing the core dist files:

  1. runGatewayUpdate() replaces dist files on disk (new content-hashed filenames)
  2. updatePluginsAfterCoreUpdate() runs in the same (old) process
  3. src/plugins/install.ts uses a lazy dynamic import: import("./install.runtime.js")
  4. The old install.js chunk references install.runtime-BEOb-kNW.js (old hash)
  5. But on disk it is now install.runtime-Xyz12345.js (new hash) -> ERR_MODULE_NOT_FOUND

The lazy import in install.ts (line 19-23) was introduced to avoid heavyweight imports at module load time, but it means the import is resolved after the files have been replaced:

let pluginInstallRuntimePromise: Promise<typeof import("./install.runtime.js")> | undefined;
async function loadPluginInstallRuntime() {
  pluginInstallRuntimePromise ??= import("./install.runtime.js");
  return pluginInstallRuntimePromise;
}

This issue did not exist before ~2026-02-28 because:

  • The auto-updater was added on 2026-02-22 (f442a353)
  • Various install refactors in Feb introduced the lazy import pattern to avoid startup stalls (see PR #46301)

Code Example

Failed to update dingtalk: Error [ERR_MODULE_NOT_FOUND]: Cannot find module
'/home/tom/.nvm/versions/node/v22.22.1/lib/node_modules/openclaw/dist/install.runtime-BEOb-kNW.js'
imported from '/home/tom/.nvm/versions/node/v22.22.1/lib/node_modules/openclaw/dist/install-Ca5qyNuE.js'

---

let pluginInstallRuntimePromise: Promise<typeof import("./install.runtime.js")> | undefined;
async function loadPluginInstallRuntime() {
  pluginInstallRuntimePromise ??= import("./install.runtime.js");
  return pluginInstallRuntimePromise;
}
RAW_BUFFERClick to expand / collapse

Summary

Running openclaw update after a new release fails to update plugins on the first attempt with:

Failed to update dingtalk: Error [ERR_MODULE_NOT_FOUND]: Cannot find module
'/home/tom/.nvm/versions/node/v22.22.1/lib/node_modules/openclaw/dist/install.runtime-BEOb-kNW.js'
imported from '/home/tom/.nvm/versions/node/v22.22.1/lib/node_modules/openclaw/dist/install-Ca5qyNuE.js'

Running openclaw update a second time succeeds.

Root Cause

The update flow in src/cli/update-cli/update-command.ts runs plugin updates in the same process after replacing the core dist files:

  1. runGatewayUpdate() replaces dist files on disk (new content-hashed filenames)
  2. updatePluginsAfterCoreUpdate() runs in the same (old) process
  3. src/plugins/install.ts uses a lazy dynamic import: import("./install.runtime.js")
  4. The old install.js chunk references install.runtime-BEOb-kNW.js (old hash)
  5. But on disk it is now install.runtime-Xyz12345.js (new hash) -> ERR_MODULE_NOT_FOUND

The lazy import in install.ts (line 19-23) was introduced to avoid heavyweight imports at module load time, but it means the import is resolved after the files have been replaced:

let pluginInstallRuntimePromise: Promise<typeof import("./install.runtime.js")> | undefined;
async function loadPluginInstallRuntime() {
  pluginInstallRuntimePromise ??= import("./install.runtime.js");
  return pluginInstallRuntimePromise;
}

This issue did not exist before ~2026-02-28 because:

  • The auto-updater was added on 2026-02-22 (f442a353)
  • Various install refactors in Feb introduced the lazy import pattern to avoid startup stalls (see PR #46301)

Suggested Fix

Option A: After runGatewayUpdate() replaces the dist files, spawn a child process using the new binary to run plugin updates, rather than continuing in the stale process.

Option B: Eagerly resolve the install.runtime.js import before runGatewayUpdate() replaces the files, so the module is already cached in memory when plugin updates run.

Environment

  • Node.js v22.22.1
  • Global npm install
  • Linux
  • Affects all npm-installed plugins

Reproduction

  1. Have any npm-installed plugin
  2. Wait for a new openclaw release
  3. Run openclaw update
  4. Observe plugin update failure
  5. Run openclaw update again - succeeds

extent analysis

TL;DR

Run openclaw update in a separate process after replacing dist files to avoid module not found errors.

Guidance

  • Consider using Option A from the suggested fix: spawn a child process using the new binary to run plugin updates after runGatewayUpdate() replaces the dist files.
  • Alternatively, explore Option B: eagerly resolve the install.runtime.js import before runGatewayUpdate() replaces the files to cache the module in memory.
  • Verify the fix by running openclaw update and checking if plugin updates succeed on the first attempt.
  • To mitigate the issue temporarily, running openclaw update twice, as described in the reproduction steps, can still update plugins successfully.

Example

No explicit code example is provided, but the suggested fix options (A and B) imply modifying the update-command.ts file to either spawn a child process or eagerly resolve the install.runtime.js import.

Notes

The issue is specific to the combination of Node.js v22.22.1, global npm install, and Linux environment, and affects all npm-installed plugins. The suggested fixes aim to address the root cause of the problem, which is the lazy dynamic import in install.ts resolving after the files have been replaced.

Recommendation

Apply workaround Option A: spawn a child process using the new binary to run plugin updates after runGatewayUpdate() replaces the dist files, as it seems to be a more straightforward and effective solution to avoid the module not found errors.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING