openclaw - 💡(How to fix) Fix [Feature]: Upgrade flow for bundled→external plugin migrations (peerDependencies chicken-and-egg)

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…

Provide an operator-facing flow for bundled→external plugin migrations that doesn't require running npm install -g openclaw@<new> destructively to discover which @openclaw/<id> packages need pre-installation.

Root Cause

  1. On the OLD binary, openclaw plugins install @openclaw/<id> fails because the package's peerDependencies.openclaw gates on >=<new>. Pre-installing externals against the old binary is impossible by design.
  2. On the NEW binary, the plugin set silently shrinks at gateway start because the externals aren't installed yet. The startup [gateway] http server listening (... plugins: ...) line drops them with no warning if plugins.entries.<id> wasn't explicitly pinned in openclaw.json.
  3. The "install them and retry" guidance some doctor / install paths surface is only actionable AFTER the destructive npm install -g openclaw@<new> has already run — i.e., during a downtime window when the operator is already mid-rollback decision.

Fix Action

Fix / Workaround

  • Status quo (manual recovery). Operator runs the destructive install, observes the breakage, then runs openclaw plugins install @openclaw/<id> for each missing external. Works but requires HITL and is silent until after impact.
  • peerDependencies softening. Loosening the peer-dep gate on externals would let operators pre-install against the old binary. Rejected: the peer-dep is correct — externals genuinely target a specific OpenClaw API surface, and silent install against an incompatible binary would be worse.
  • Doctor-only warning. Surfacing "you will lose X plugins on the next upgrade to <ver>" in openclaw doctor. Useful but doesn't solve the chicken-and-egg; it just makes the trap visible.

In our deployment (a Discord-tenant agent on Ubuntu NUC), the 2026.4.29 → 2026.5.7 upgrade dropped acpx and discord from the listening line silently. We hit this in the field 2026-05-11 and built a workaround in our upgrade orchestrator:

The full 60-second preflight pays for itself by avoiding the ~5-minute destructive-install + rollback round-trip and the Discord-noise it produces on every bundled→external regression. A first-class openclaw upgrade would obviate the entire workaround.

Code Example

systemctl --user stop openclaw-gateway
npm install -g openclaw@<new>
openclaw plugins install @openclaw/<id>@<new>   # for each externalized plugin
systemctl --user start openclaw-gateway
RAW_BUFFERClick to expand / collapse

Summary

Provide an operator-facing flow for bundled→external plugin migrations that doesn't require running npm install -g openclaw@<new> destructively to discover which @openclaw/<id> packages need pre-installation.

Problem to solve

When a previously-bundled plugin (e.g., acpx, discord) is moved to a separate @openclaw/<id> npm package (per release notes "trust official externalized npm migrations, clean stale bundled load paths for externalized installs", 2026.5.4), operators upgrading from a release that predates the migration hit a chicken-and-egg:

  1. On the OLD binary, openclaw plugins install @openclaw/<id> fails because the package's peerDependencies.openclaw gates on >=<new>. Pre-installing externals against the old binary is impossible by design.
  2. On the NEW binary, the plugin set silently shrinks at gateway start because the externals aren't installed yet. The startup [gateway] http server listening (... plugins: ...) line drops them with no warning if plugins.entries.<id> wasn't explicitly pinned in openclaw.json.
  3. The "install them and retry" guidance some doctor / install paths surface is only actionable AFTER the destructive npm install -g openclaw@<new> has already run — i.e., during a downtime window when the operator is already mid-rollback decision.

The class is silent for the most common config shape: an operator running bundled defaults (no plugins.entries.<id> entry) has no warning surface telling them which externals their live gateway will be using on the new binary. The first observable symptom is broken Discord, missing mDNS, etc., after the destructive install.

Proposed solution

Either of these closes the gap:

(a) Documentation pattern. Document the deterministic "install during downtime" recipe:

systemctl --user stop openclaw-gateway
npm install -g openclaw@<new>
openclaw plugins install @openclaw/<id>@<new>   # for each externalized plugin
systemctl --user start openclaw-gateway

Plus a way to identify which <id>s need installing against a given version — e.g., a openclaw upgrade --plan <ver> command that compares the live binary's loaded plugin set against the staged binary's bundled set and prints the required externals.

(b) First-class openclaw upgrade command. A single atomic operation: stop gateway → npm install -g openclaw@<ver> → for each plugin currently loaded but no longer bundled in <ver>, run openclaw plugins install @openclaw/<id>@<ver> → start gateway → wait for ready. Failure rolls back the openclaw install. This makes the externalized plugins behave like first-class package installs end-to-end (which the 2026.5.4 release notes claim as the goal, but only at the per-plugin install level — not at the upgrade-of-openclaw-itself level).

Alternatives considered

  • Status quo (manual recovery). Operator runs the destructive install, observes the breakage, then runs openclaw plugins install @openclaw/<id> for each missing external. Works but requires HITL and is silent until after impact.
  • peerDependencies softening. Loosening the peer-dep gate on externals would let operators pre-install against the old binary. Rejected: the peer-dep is correct — externals genuinely target a specific OpenClaw API surface, and silent install against an incompatible binary would be worse.
  • Doctor-only warning. Surfacing "you will lose X plugins on the next upgrade to <ver>" in openclaw doctor. Useful but doesn't solve the chicken-and-egg; it just makes the trap visible.

Impact

  • Affected. Every operator running on a release that predates a bundled→external migration. The 2026.5.4 migration alone moved acpx, bonjour, discord — anyone upgrading from 2026.4.x to 2026.5.4+ trips this if they use any of those channels.
  • Severity. High during the migration window — Discord operators lose openclaw message read round-trip and webhook delivery silently. The breakage is post-install and pre-rollback.
  • Frequency. Once per operator per migration. Each future bundled→external split will produce a fresh occurrence for the population that hadn't yet upgraded.
  • Consequence. Either an unplanned rollback round-trip (~5 min on a ~/.cache/juno/openclaw-rollback-*.tgz-style snapshot setup) or several minutes of broken delivery before the operator notices and manually installs the externals.

Evidence/examples

In our deployment (a Discord-tenant agent on Ubuntu NUC), the 2026.4.29 → 2026.5.7 upgrade dropped acpx and discord from the listening line silently. We hit this in the field 2026-05-11 and built a workaround in our upgrade orchestrator:

The full 60-second preflight pays for itself by avoiding the ~5-minute destructive-install + rollback round-trip and the Discord-noise it produces on every bundled→external regression. A first-class openclaw upgrade would obviate the entire workaround.

Additional information

  • The smoke probes that catch the breakage post-install on our side are openclaw message read --channel discord --target <#channel> --limit 1 (exits in <8 s on healthy gateway) and a webhook-posted message round-trip — both are after-the-fact, not before-the-fact.
  • We currently retain a tarball snapshot of the prior ~/.npm-global/lib/node_modules/openclaw + matching ~/.openclaw/openclaw.json so the rollback path is fast (~5 min including gateway restart). A first-class upgrade flow would reduce this to a documentation footnote rather than mandatory infrastructure.

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 - 💡(How to fix) Fix [Feature]: Upgrade flow for bundled→external plugin migrations (peerDependencies chicken-and-egg)