openclaw - ✅(Solved) Fix Bundled-plugin stageRuntimeDependencies fails under ProtectSystem=strict (EROFS; gateway can't write /usr/lib) [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#69923Fetched 2026-04-22 07:46:38
View on GitHub
Comments
1
Participants
2
Timeline
79
Reactions
0
Author
Timeline (top)
cross-referenced ×40marked_as_duplicate ×36subscribed ×2commented ×1

Error Message

{ "status": "error", "reason": "openclaw doctor", "steps": [ { "name": "global update", "exitCode": 0, "stdoutTail": "changed 454 packages in 36s" }, { "name": "openclaw doctor", "exitCode": 1, "stderrTail": "Error: Cannot find module '@slack/web-api'\nRequire stack:\n- /usr/lib/node_modules/openclaw/dist/extensions/slack/client-*.js" } ] }

Root Cause

The 2026.4.20 plugin-repair path (src/plugins/loader.ts, per release notes: "install bundled runtime dependencies into each plugin's own runtime directory") attempts to write into /usr/lib/node_modules/openclaw/dist/extensions/<id>/node_modules/. Under ProtectSystem=strict that path is mounted read-only inside the service's mount namespace, and NoNewPrivileges=yes blocks any sudo escalation. The staging call fails with EROFS and is silently swallowed; subsequent plugin imports then fail module resolution and openclaw doctor crashes.

openclaw doctor --fix doesn't perform staging either — it imports plugins eagerly and crashes on the same missing module before any repair logic runs. There is no documented openclaw plugins install-deps or equivalent CLI.

Fix Action

Fix / Workaround

Current workaround

Patched our update wrapper to run npm install --ignore-scripts --no-fund --no-audit as root in each bundled plugin dir that declares stageRuntimeDependencies: true and lacks node_modules/. Invoked in a recovery branch when openclaw update exits with "reason": "openclaw doctor" + Cannot find module '@, and unconditionally post-update (because npm i -g openclaw@latest wipes plugin node_modules/ on every run, even on same-version reinstalls).

Happy to share the wrapper patch if it helps.

PR fix notes

PR #37602: fix(docker): install extension dependencies in Dockerfile

Description (problem / solution / changelog)

fix(docker): install extension dependencies in Dockerfile

Problem

Extension plugins like feishu failed to load in Docker with module not found errors:

Error: Cannot find module '@larksuiteoapi/node-sdk'
Require stack:
- /app/extensions/feishu/src/client.ts

The Dockerfile's initial pnpm install --frozen-lockfile ran before copying the extensions/ directory, so extension dependencies were never installed.

Solution

Added pnpm install --no-frozen-lockfile after COPY . . to ensure extension dependencies are installed before building.

Changes

  • Modified Dockerfile to add extension dependency installation step after copying source code

Testing

  • ✅ Built Docker image successfully
  • ✅ Verified /app/extensions/feishu/node_modules/@larksuiteoapi is present in container
  • ✅ Confirmed feishu plugin loads without errors
  • ✅ Gateway runs normally with all extensions functional

Impact

  • Fixes all extension plugins that require external dependencies
  • Minimal build time impact (~few seconds for extension deps)
  • No changes to runtime behavior or existing functionality

Co-Authored-By: 赵浩dong [email protected] Co-Authored-By: Claude Sonnet 4.5 [email protected]

Changed files

  • Dockerfile (modified, +2/-0)

Code Example

{
  "status": "error",
  "reason": "openclaw doctor",
  "steps": [
    { "name": "global update",    "exitCode": 0, "stdoutTail": "changed 454 packages in 36s" },
    { "name": "openclaw doctor",  "exitCode": 1,
      "stderrTail": "Error: Cannot find module '@slack/web-api'\nRequire stack:\n- /usr/lib/node_modules/openclaw/dist/extensions/slack/client-*.js" }
  ]
}
RAW_BUFFERClick to expand / collapse

Environment

  • OpenClaw 2026.4.20 (also reproduced on 2026.4.15)
  • Installed via npm i -g openclaw@latest to /usr/lib/node_modules/openclaw/
  • Running under systemd with hardened unit:
    • ProtectSystem=strict
    • ProtectHome=read-only
    • NoNewPrivileges=yes
    • ReadWritePaths=/mnt/data/.openclaw /home/openclaw/.openclaw /tmp … (narrow allowlist; /usr/lib/ excluded)

Symptom

After openclaw update --yes --no-restart --json:

{
  "status": "error",
  "reason": "openclaw doctor",
  "steps": [
    { "name": "global update",    "exitCode": 0, "stdoutTail": "changed 454 packages in 36s" },
    { "name": "openclaw doctor",  "exitCode": 1,
      "stderrTail": "Error: Cannot find module '@slack/web-api'\nRequire stack:\n- /usr/lib/node_modules/openclaw/dist/extensions/slack/client-*.js" }
  ]
}

No node_modules/ directory exists in any /usr/lib/node_modules/openclaw/dist/extensions/*/. All 15 bundled plugins that declare "openclaw.bundle.stageRuntimeDependencies": true (slack, discord, telegram, whatsapp, feishu, matrix, qqbot, nostr, webhooks, codex, google, diffs, acpx, amazon-bedrock, amazon-bedrock-mantle) have their deps missing.

Root cause

The 2026.4.20 plugin-repair path (src/plugins/loader.ts, per release notes: "install bundled runtime dependencies into each plugin's own runtime directory") attempts to write into /usr/lib/node_modules/openclaw/dist/extensions/<id>/node_modules/. Under ProtectSystem=strict that path is mounted read-only inside the service's mount namespace, and NoNewPrivileges=yes blocks any sudo escalation. The staging call fails with EROFS and is silently swallowed; subsequent plugin imports then fail module resolution and openclaw doctor crashes.

openclaw doctor --fix doesn't perform staging either — it imports plugins eagerly and crashes on the same missing module before any repair logic runs. There is no documented openclaw plugins install-deps or equivalent CLI.

Related reports

  • #61787 (open 2026-04-21) — npm global install of 2026.4.x silently omits channel plugin deps (exact match for our install method)
  • #60004, #58922, #63043, #61363 — earlier reports of the same symptom under different plugin combinations

Proposed fixes (in preference order)

  1. Env-overridable staging target. Accept OPENCLAW_PLUGIN_STAGE_DIR (or $STATE_DIRECTORY from the systemd unit) so operators can point staging at a ReadWritePaths-included directory. Lets hardened hosts stage deps without loosening ProtectSystem=strict on the gateway unit.
  2. Explicit openclaw plugins install-deps CLI that installs all bundled-plugin deps on demand, runnable from an out-of-namespace context (e.g., a systemd ExecStartPre= unit or update hook). Wrappers can call this instead of implementing custom staging logic.
  3. Document the incompatibility between stageRuntimeDependencies and ProtectSystem=strict in docs/install/ so operators know either to loosen hardening or pre-stage deps before enabling.

Current workaround

Patched our update wrapper to run npm install --ignore-scripts --no-fund --no-audit as root in each bundled plugin dir that declares stageRuntimeDependencies: true and lacks node_modules/. Invoked in a recovery branch when openclaw update exits with "reason": "openclaw doctor" + Cannot find module '@, and unconditionally post-update (because npm i -g openclaw@latest wipes plugin node_modules/ on every run, even on same-version reinstalls).

Happy to share the wrapper patch if it helps.

extent analysis

TL;DR

The most likely fix is to set an environment variable OPENCLAW_PLUGIN_STAGE_DIR to a writable directory included in ReadWritePaths to allow OpenClaw to stage dependencies without loosening ProtectSystem=strict.

Guidance

  • Verify that the OPENCLAW_PLUGIN_STAGE_DIR environment variable is not already set and that the target directory is included in ReadWritePaths to ensure write access.
  • Consider implementing an openclaw plugins install-deps CLI command to install dependencies on demand, as proposed in the issue.
  • Check the documentation for any updates on the incompatibility between stageRuntimeDependencies and ProtectSystem=strict to ensure awareness of potential issues.
  • If the above solutions are not feasible, apply the current workaround of running npm install in each bundled plugin directory that declares stageRuntimeDependencies: true and lacks node_modules/.

Example

No code snippet is provided as the issue does not require a specific code change, but rather a configuration or environment variable adjustment.

Notes

The proposed fixes and workarounds may have varying degrees of effectiveness depending on the specific environment and configuration. It is essential to test and verify any changes before implementing them in production.

Recommendation

Apply the workaround of setting OPENCLAW_PLUGIN_STAGE_DIR to a writable directory, as it is a relatively simple and non-invasive solution that can help mitigate the issue without requiring significant changes to the OpenClaw configuration or code.

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

openclaw - ✅(Solved) Fix Bundled-plugin stageRuntimeDependencies fails under ProtectSystem=strict (EROFS; gateway can't write /usr/lib) [1 pull requests, 1 comments, 2 participants]