openclaw - ✅(Solved) Fix Bundled runtime deps can recursively stage from the canonical stage root, generating openclaw-unknown-* and split-stage runtime resolution on 2026.4.24 [1 pull requests, 1 comments, 2 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#71978Fetched 2026-04-27 05:36:34
View on GitHub
Comments
1
Participants
2
Timeline
4
Reactions
0
Participants
Timeline (top)
cross-referenced ×2closed ×1commented ×1

On a packaged 2026.4.24 install, bundled runtime dependency staging can deterministically generate an anomalous secondary stage directory like ~/.openclaw/plugin-runtime-deps/openclaw-unknown-a44f41aef101.

This is not stale residue: the running Gateway can actively resolve modules from that unknown stage.

The strongest local root-cause evidence suggests a second staging pass is using the already-generated canonical stage root as packageRoot, so readPackageVersion(packageRoot) falls back to unknown, and createPathHash(packageRoot) hashes the canonical stage path.

Error Message

  • [channels] failed to load bundled channel whatsapp: npm error code 128

Root Cause

On a packaged 2026.4.24 install, bundled runtime dependency staging can deterministically generate an anomalous secondary stage directory like ~/.openclaw/plugin-runtime-deps/openclaw-unknown-a44f41aef101.

This is not stale residue: the running Gateway can actively resolve modules from that unknown stage.

The strongest local root-cause evidence suggests a second staging pass is using the already-generated canonical stage root as packageRoot, so readPackageVersion(packageRoot) falls back to unknown, and createPathHash(packageRoot) hashes the canonical stage path.

Fix Action

Fix / Workaround

Environment

  • OpenClaw version: 2026.4.24
  • Packaged install root: /usr/lib/node_modules/openclaw
  • Canonical runtime deps stage root resolved by bundled runtime code:
    • /root/.openclaw/plugin-runtime-deps/openclaw-2026.4.24-4eca5026e977
  • Recurrently generated anomalous stage:
    • /root/.openclaw/plugin-runtime-deps/openclaw-unknown-a44f41aef101
  • Host type: Linux/systemd packaged install

Impact

  • Split-stage runtime state (canonical + unknown)
  • Recurrent restaging on restart
  • Runtime module resolution may land in the anomalous stage
  • One-time cleanup does not stick
  • Operationally, users may be forced into symlink-based stabilization/workarounds just to keep runtime deps resolvable across restarts

Practical workaround currently required

On this affected host, the only stable workaround found so far is to let both:

  • canonical stage root
  • anomalous unknown stage root

PR fix notes

PR #71983: fix(plugins): fallback npm_config_cache to os.tmpdir() (v5)

Description (problem / solution / changelog)

v5 of fix from #71614, #71926, #71935, #71945, #71966 (all auto-closed by stale-PR cleanup).

Use os.tmpdir() as safe fallback when npm_config_cache is unset, preventing npm from writing under $HOME/node_modules during bundled runtime dependency installs.

Fix: src/plugins/bundled-runtime-deps.tscreateBundledRuntimeDepsInstallEnv (+2 lines)

Changed files

  • src/plugins/bundled-runtime-deps.ts (modified, +2/-0)

Code Example

const packageRoot = resolveBundledPluginPackageRoot(params.pluginRoot) ?? params.pluginRoot;
const packageKey = `openclaw-${sanitizePathSegment(readPackageVersion(packageRoot))}-${createPathHash(packageRoot)}`;

---

function readPackageVersion(packageRoot) {
  const parsed = readJsonObject(path.join(packageRoot, 'package.json'));
  return (parsed && typeof parsed.version === 'string' ? parsed.version.trim() : '') || 'unknown';
}
RAW_BUFFERClick to expand / collapse

Summary

On a packaged 2026.4.24 install, bundled runtime dependency staging can deterministically generate an anomalous secondary stage directory like ~/.openclaw/plugin-runtime-deps/openclaw-unknown-a44f41aef101.

This is not stale residue: the running Gateway can actively resolve modules from that unknown stage.

The strongest local root-cause evidence suggests a second staging pass is using the already-generated canonical stage root as packageRoot, so readPackageVersion(packageRoot) falls back to unknown, and createPathHash(packageRoot) hashes the canonical stage path.

Environment

  • OpenClaw version: 2026.4.24
  • Packaged install root: /usr/lib/node_modules/openclaw
  • Canonical runtime deps stage root resolved by bundled runtime code:
    • /root/.openclaw/plugin-runtime-deps/openclaw-2026.4.24-4eca5026e977
  • Recurrently generated anomalous stage:
    • /root/.openclaw/plugin-runtime-deps/openclaw-unknown-a44f41aef101
  • Host type: Linux/systemd packaged install

Expected behavior

Bundled runtime deps should stage once from the real package root and consistently use the canonical stage directory for this packaged install.

Actual behavior

A second anomalous stage named openclaw-unknown-* is generated on restart and can become part of active runtime resolution.

Key evidence

1) Canonical packaged-install stage root is correct and stable

Local code-path verification of bundled runtime helpers showed the intended packaged-install root is the external runtime-deps stage, not /usr/lib/node_modules/openclaw/node_modules.

Resolved values observed locally:

  • resolveBundledRuntimeDependencyPackageInstallRoot('/usr/lib/node_modules/openclaw', {env}) -> /root/.openclaw/plugin-runtime-deps/openclaw-2026.4.24-4eca5026e977
  • resolveBundledRuntimeDependencyInstallRoot('/usr/lib/node_modules/openclaw/dist/extensions/browser', {env}) -> same canonical root
  • resolveBundledRuntimeDependencyInstallRoot('/usr/lib/node_modules/openclaw/dist/extensions/feishu', {env}) -> same canonical root

2) openclaw-unknown-* is actively used, not stale

Post-start logs referenced modules from the anomalous stage, e.g. stack traces resolving through:

  • /root/.openclaw/plugin-runtime-deps/openclaw-unknown-a44f41aef101/node_modules/axios/dist/node/axios.cjs
  • /root/.openclaw/plugin-runtime-deps/openclaw-unknown-a44f41aef101/node_modules/follow-redirects/index.js

3) unknown is regenerated on restart

After quarantining/removing the anomalous stage and restarting the Gateway, it reappeared with fresh timestamps after service start, proving recurrence rather than historical residue.

4) The anomalous stage contains real bundled extension mirror contents

/root/.openclaw/plugin-runtime-deps/openclaw-unknown-a44f41aef101/dist/extensions contained many bundled channels/extensions (for example signal, imessage, mattermost, qqbot, msteams, telegram, googlechat, feishu, slack, discord, etc.), showing it is part of a normal staging/mirroring flow under degraded identity.

5) Bundled channel load failures also write npm cache under unknown

Observed log example:

  • [channels] failed to load bundled channel whatsapp: npm error code 128
  • npm log path under: /root/.openclaw/plugin-runtime-deps/openclaw-unknown-a44f41aef101/.openclaw-npm-cache/_logs/...

This strongly suggests bundled channel runtime staging/loading is happening under the anomalous root.

6) The hash suffix a44f41aef101 matches the canonical stage root path

By reproducing the hash logic locally, a44f41aef101 matched the path hash of:

  • /root/.openclaw/plugin-runtime-deps/openclaw-2026.4.24-4eca5026e977

That means the anomalous directory name:

  • openclaw-unknown-a44f41aef101

is consistent with computing:

  • readPackageVersion(packageRoot) -> 'unknown'
  • createPathHash(packageRoot) -> hash(canonical_stage_root_path)

This is the strongest indicator that a second staging pass is using the already-generated canonical stage root as packageRoot.

Relevant code shape observed locally

From bundled runtime code:

const packageRoot = resolveBundledPluginPackageRoot(params.pluginRoot) ?? params.pluginRoot;
const packageKey = `openclaw-${sanitizePathSegment(readPackageVersion(packageRoot))}-${createPathHash(packageRoot)}`;

And:

function readPackageVersion(packageRoot) {
  const parsed = readJsonObject(path.join(packageRoot, 'package.json'));
  return (parsed && typeof parsed.version === 'string' ? parsed.version.trim() : '') || 'unknown';
}

If packageRoot is accidentally the canonical stage root, there is no valid top-level package version there, so unknown is expected.

Impact

  • Split-stage runtime state (canonical + unknown)
  • Recurrent restaging on restart
  • Runtime module resolution may land in the anomalous stage
  • One-time cleanup does not stick
  • Operationally, users may be forced into symlink-based stabilization/workarounds just to keep runtime deps resolvable across restarts

Practical workaround currently required

On this affected host, the only stable workaround found so far is to let both:

  • canonical stage root
  • anomalous unknown stage root

resolve the same node_modules, rather than trying to delete unknown permanently.

What seems worth checking upstream

  • Whether bundled runtime deps / mirror code can accidentally feed a stage root back into package-root resolution during a second staging pass
  • Whether resolveBundledPluginPackageRoot(...) / mirror remap logic can return a staged path instead of the original package root
  • Whether stage roots should carry enough metadata to avoid unknown, or better, whether they should never be treated as package roots at all
  • Whether bundled channel loading (e.g. whatsapp) is triggering this path especially often

If useful, I can also provide

  • exact restart timeline / timestamps showing regeneration order
  • exact file paths and code references from the packaged dist/*.js files inspected locally
  • log excerpts for the whatsapp failure and unknown npm cache path

extent analysis

TL;DR

The most likely fix is to prevent the second staging pass from using the already-generated canonical stage root as packageRoot, which causes readPackageVersion(packageRoot) to fall back to unknown.

Guidance

  • Review the resolveBundledPluginPackageRoot function to ensure it returns the original package root instead of the staged path.
  • Verify that the mirror remap logic does not feed a stage root back into package-root resolution during a second staging pass.
  • Consider adding metadata to stage roots to avoid treating them as package roots or to prevent unknown package versions.
  • Investigate if bundled channel loading is triggering the anomalous stage generation, especially for channels like whatsapp.

Example

No code snippet is provided as the issue is more related to the logic and flow of the application rather than a specific code block.

Notes

The provided information suggests that the issue is related to the staging process and package root resolution. However, without more context or code, it's difficult to provide a definitive solution. The suggested guidance points are based on the information provided and may need to be adapted to the specific application and its requirements.

Recommendation

Apply a workaround to let both the canonical stage root and the anomalous unknown stage root resolve the same node_modules, rather than trying to delete unknown permanently, until a more permanent fix can be implemented. This will allow the application to function stably across restarts.

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…

FAQ

Expected behavior

Bundled runtime deps should stage once from the real package root and consistently use the canonical stage directory for this packaged install.

Still need to ship something?

×6

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

Back to top recommendations

TRENDING

openclaw - ✅(Solved) Fix Bundled runtime deps can recursively stage from the canonical stage root, generating openclaw-unknown-* and split-stage runtime resolution on 2026.4.24 [1 pull requests, 1 comments, 2 participants]