openclaw - ✅(Solved) Fix postinstall-bundled-plugins fails silently without SSH client, leaving runtime deps missing [1 pull requests, 1 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#62952Fetched 2026-04-09 08:00:17
View on GitHub
Comments
0
Participants
1
Timeline
2
Reactions
0
Participants
Timeline (top)
cross-referenced ×2

postinstall-bundled-plugins.mjs fails silently when the container image lacks an SSH client (openssh-client). Some transitive dependencies use git+ssh:// URLs (e.g., whiskeysockets/libsignal-node). When SSH is unavailable, the postinstall catches the error and continues, leaving critical runtime dependencies like @buape/carbon, @slack/web-api, etc. missing.

The gateway then crashes at runtime with Cannot find module '@buape/carbon' on every HTTP request.

Error Message

postinstall-bundled-plugins.mjs fails silently when the container image lacks an SSH client (openssh-client). Some transitive dependencies use git+ssh:// URLs (e.g., whiskeysockets/libsignal-node). When SSH is unavailable, the postinstall catches the error and continues, leaving critical runtime dependencies like @buape/carbon, @slack/web-api, etc. missing. The postinstall script uses npm to install missing deps, but some transitive deps reference SSH URLs. Without SSH, npm fails. The error is caught (non-fatal by design in runBundledPluginPostinstall) and the gateway starts without these packages. Either vendor these deps in the published package, use HTTPS URLs instead of SSH, or make the postinstall error more visible (e.g., log a warning that persists to gateway startup).

Root Cause

The postinstall script uses npm to install missing deps, but some transitive deps reference SSH URLs. Without SSH, npm fails. The error is caught (non-fatal by design in runBundledPluginPostinstall) and the gateway starts without these packages.

Fix Action

Workaround

Install git, ca-certificates, and rewrite SSH URLs to HTTPS before npm install -g openclaw:

RUN apt-get install -y git ca-certificates && \
    git config --global url."https://github.com/".insteadOf "ssh://[email protected]/" && \
    npm install -g openclaw@latest

PR fix notes

PR #63065: release: mirror bundled channel deps at root

Description (problem / solution / changelog)

Summary

  • Problem: bundled Slack, Telegram, Discord, and Feishu runtime packages were still imported from root dist/*.js chunks, but they were not mirrored in the root npm manifest.
  • Why it matters: fresh installs and upgrades could ship a broken package that depended on best-effort postinstall recovery, which matched the missing-module failures in #62749, #62952, #62994, and #63043.
  • What changed: mirrored the root-resolved bundled channel deps into the root manifest, declared them through openclaw.releaseChecks.rootDependencyMirrorAllowlist, and hardened the npm postpublish verifier to check mirrored deps plus run the installed openclaw --version binary.
  • What did NOT change (scope boundary): I did not change bundled plugin staging behavior for extension-local node_modules, nor the self-update flow from #62984.

Change Type (select all)

  • Bug fix
  • Feature
  • Refactor required for the fix
  • Docs
  • Security hardening
  • Chore/infra

Scope (select all touched areas)

  • Gateway / orchestration
  • Skills / tool execution
  • Auth / tokens
  • Memory / storage
  • Integrations
  • API / contracts
  • UI / DX
  • CI/CD / infra

Linked Issue/PR

  • Closes #62749
  • Related #62952
  • Related #62994
  • Related #63043
  • This PR fixes a bug or regression

Root Cause (if applicable)

  • Root cause: bundled channel/plugin code was code-split into root dist/*.js chunks that resolve packages from the package root, but the root npm manifest did not mirror those runtime dependencies.
  • Missing detection / guardrail: the existing release checks only validated a small set of mirrored deps and the postpublish verify path did not exercise the installed openclaw binary or validate mirrored root deps from bundled extension manifests.
  • Contributing context (if known): the package still relied on best-effort postinstall repair, so environments where that recovery path failed surfaced user-visible missing-module crashes.

Regression Test Plan (if applicable)

  • Coverage level that should have caught this:
    • Unit test
    • Seam / integration test
    • End-to-end test
    • Existing coverage already sufficient
  • Target test or file: test/openclaw-npm-postpublish-verify.test.ts
  • Scenario the test should lock in: bundled extensions that declare root-mirrored runtime deps must be satisfied by the installed package root manifest, and published install verification must reject drift.
  • Why this is the smallest reliable guardrail: it validates the packaged manifest contract directly without needing a full publish cycle.
  • Existing test that already covers this (if any): test/release-check.test.ts already covers the generic root-mirror allowlist rules.
  • If no new test is added, why not: N/A

User-visible / Behavior Changes

  • npm installs now carry the bundled channel runtime deps that root dist/*.js chunks actually import, instead of relying on postinstall recovery to backfill them.
  • Postpublish verification now fails if the installed package loses those mirrored deps or if the installed openclaw binary cannot report its version.

Diagram (if applicable)

Before:
[npm install openclaw] -> [root dist chunk imports bundled channel package] -> [package missing at root] -> [runtime crash unless postinstall recovers]

After:
[npm install openclaw] -> [root manifest already mirrors root-resolved bundled channel deps] -> [runtime import resolves] -> [binary smoke + postpublish verify catch drift]

Security Impact (required)

  • New permissions/capabilities? (No)
  • Secrets/tokens handling changed? (No)
  • New/changed network calls? (No)
  • Command/tool execution surface changed? (No)
  • Data access scope changed? (No)
  • If any Yes, explain risk + mitigation:

Repro + Verification

Environment

  • OS: macOS 15.7.1 host
  • Runtime/container: Node 25 host tooling, repo release scripts
  • Model/provider: N/A
  • Integration/channel (if any): Slack / Telegram / Discord / Feishu packaging surfaces
  • Relevant config (redacted): N/A

Steps

  1. Build the repo release artifact surfaces.
  2. Run the packaging checks and postpublish verifier unit tests.
  3. Confirm root dist/*.js imports are mirrored in the root manifest through extension allowlists.

Expected

  • Release checks pass.
  • The packaged manifest explicitly mirrors root-resolved bundled channel deps.
  • Postpublish verification would fail if those mirrored deps drift again.

Actual

  • pnpm release:check passed after pnpm build and pnpm ui:build.
  • Targeted verifier tests passed.
  • The four affected bundled extensions now declare the mirrored root deps they require.

Evidence

Attach at least one:

  • Failing test/log before + passing after
  • Trace/log snippets
  • Screenshot/recording
  • Perf numbers (if relevant)

Human Verification (required)

  • Verified scenarios: pnpm test test/openclaw-npm-postpublish-verify.test.ts, pnpm test test/release-check.test.ts, pnpm build, pnpm ui:build, pnpm release:check
  • Edge cases checked: optional root mirror for @discordjs/opus; installed-package manifest drift detection for mirrored bundled deps
  • What you did not verify: I did not fully re-test the separate Web UI self-update corruption path from #62984, and the local tarball global-install smoke was slower than the targeted release checks so I relied on the hardened verifier + release gate rather than waiting for that extra run.

Review Conversations

  • I replied to or resolved every bot review conversation I addressed in this PR.
  • I left unresolved only the conversations that still need reviewer or maintainer judgment.

Compatibility / Migration

  • Backward compatible? (Yes)
  • Config/env changes? (No)
  • Migration needed? (No)
  • If yes, exact upgrade steps:

Risks and Mitigations

  • Risk: root dependency surface grows for the mirrored bundled channel packages.
    • Mitigation: each added mirror is now declared by the owning extension through rootDependencyMirrorAllowlist, checked by release-check, and validated again in postpublish verification.

Changed files

  • CHANGELOG.md (modified, +1/-0)
  • extensions/discord/package.json (modified, +8/-0)
  • extensions/feishu/package.json (modified, +5/-0)
  • extensions/slack/package.json (modified, +7/-0)
  • extensions/telegram/package.json (modified, +7/-0)
  • package.json (modified, +10/-0)
  • pnpm-lock.yaml (modified, +31/-1)
  • scripts/openclaw-npm-postpublish-verify.ts (modified, +180/-2)
  • src/plugins/contracts/package-manifest.contract.test.ts (modified, +17/-6)
  • test/helpers/plugins/package-manifest-contract.ts (modified, +35/-5)
  • test/openclaw-npm-postpublish-verify.test.ts (modified, +187/-0)

Code Example

# In a container without openssh-client
npm install -g openclaw@latest
cd /usr/local/lib/node_modules/openclaw
npm ls @buape/carbon  # reports empty
openclaw gateway --port 18789  # crashes

---

RUN apt-get install -y git ca-certificates && \
    git config --global url."https://github.com/".insteadOf "ssh://[email protected]/" && \
    npm install -g openclaw@latest
RAW_BUFFERClick to expand / collapse

Description

postinstall-bundled-plugins.mjs fails silently when the container image lacks an SSH client (openssh-client). Some transitive dependencies use git+ssh:// URLs (e.g., whiskeysockets/libsignal-node). When SSH is unavailable, the postinstall catches the error and continues, leaving critical runtime dependencies like @buape/carbon, @slack/web-api, etc. missing.

The gateway then crashes at runtime with Cannot find module '@buape/carbon' on every HTTP request.

Repro

# In a container without openssh-client
npm install -g openclaw@latest
cd /usr/local/lib/node_modules/openclaw
npm ls @buape/carbon  # reports empty
openclaw gateway --port 18789  # crashes

Root cause

The postinstall script uses npm to install missing deps, but some transitive deps reference SSH URLs. Without SSH, npm fails. The error is caught (non-fatal by design in runBundledPluginPostinstall) and the gateway starts without these packages.

Workaround

Install git, ca-certificates, and rewrite SSH URLs to HTTPS before npm install -g openclaw:

RUN apt-get install -y git ca-certificates && \
    git config --global url."https://github.com/".insteadOf "ssh://[email protected]/" && \
    npm install -g openclaw@latest

Suggestion

Either vendor these deps in the published package, use HTTPS URLs instead of SSH, or make the postinstall error more visible (e.g., log a warning that persists to gateway startup).

Related: #62749

extent analysis

TL;DR

Install git, ca-certificates, and rewrite SSH URLs to HTTPS to ensure successful installation of dependencies.

Guidance

  • Identify and install required dependencies (git, ca-certificates) in the container image to support SSH connections or rewrite SSH URLs to HTTPS.
  • Verify the installation of dependencies using npm ls command, as shown in the repro steps.
  • Consider modifying the postinstall script to handle errors more visibly, such as logging warnings that persist to gateway startup.
  • Evaluate the suggested workarounds, including vendoring dependencies, using HTTPS URLs, or enhancing error handling in the postinstall script.

Example

The provided Dockerfile snippet demonstrates how to install required dependencies and rewrite SSH URLs to HTTPS:

RUN apt-get install -y git ca-certificates && \
    git config --global url."https://github.com/".insteadOf "ssh://[email protected]/" && \
    npm install -g openclaw@latest

Notes

This solution assumes that the issue is specific to the absence of an SSH client in the container image. The suggested workarounds may have implications for dependency management and security.

Recommendation

Apply the workaround by installing required dependencies and rewriting SSH URLs to HTTPS, as it provides a straightforward solution to the issue.

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