openclaw - ✅(Solved) Fix v2026.5.12-beta.5 plugin update disables lossless-claw after @beta fallback and leaves stale contextEngine config [2 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#81499Fetched 2026-05-14 03:31:27
View on GitHub
Comments
1
Participants
2
Timeline
7
Reactions
2
Author
Timeline (top)
cross-referenced ×3closed ×1commented ×1mentioned ×1

During a 2026.5.12-beta.4 -> 2026.5.12-beta.5 update on one macOS npm/pnpm install, configured external plugin lossless-claw had no @beta release, so the updater fell back to @latest. The beta 5 plugin scanner then blocked the installed tree for dangerous patterns in transitive dependency/example files, disabled the plugin, and left stale config references including the configured contextEngine slot.

Core OpenClaw remained healthy after update, but the host lost its configured context engine and now falls back to legacy with stale plugin config warnings.

Root Cause

  • Existing task-audit warnings on the host predated beta 5.
  • Optional model-pricing warnings did not block model routing.
  • I did not force reinstall the plugin or run openclaw doctor --fix, because either would mutate the operator state beyond update/audit verification.

Fix Action

Fixed

PR fix notes

PR #81512: [AI-assisted] fix(update): clear stale plugin refs after failed updates

Description (problem / solution / changelog)

Summary

  • Problem: plugin update failures with disableOnFailure only disabled plugins.entries.<id> and could leave stale plugins.allow, plugins.deny, and selected plugin slots pointing at the disabled plugin.
  • Why it matters: after a failed external plugin update, operators could see a half-disabled config where the context-engine slot still referenced a plugin that OpenClaw had just disabled.
  • What changed: failed-update disable now also removes the disabled plugin from allow/deny lists and resets selected memory / contextEngine slots to their defaults while preserving the install record for later repair.
  • What did NOT change: no plugin install, package scanning, fallback-channel selection, or uninstall behavior changed.

Change Type

  • Bug fix

Scope

  • API / contracts
  • UI / DX

Linked Issue/PR

  • Closes: N/A
  • Related: #81499
  • Fixes bug/regression: Yes

Real behavior proof

  • Behavior or issue addressed: failed plugin updates that disable a plugin now leave config policy and selected slots consistent with the disabled entry.
  • Real environment tested: local OpenClaw repo checkout on Windows, Node 24.14, using the real updateNpmInstalledPlugins production helper with a synthetic local config and no external credentials.
  • Exact steps or command run after this patch:
node_modules\.bin\tsx.cmd -e "import { updateNpmInstalledPlugins } from './src/plugins/update.ts'; void (async () => { const result = await updateNpmInstalledPlugins({ config: { plugins: { allow: ['demo', 'keep'], deny: ['demo', 'blocked'], slots: { memory: 'demo', contextEngine: 'demo' }, entries: { demo: { enabled: true } }, installs: { demo: { source: 'npm', spec: 'not a valid spec?', installPath: '/tmp/demo' } } } }, pluginIds: ['demo'], disableOnFailure: true, logger: { warn: () => undefined } }); console.log(JSON.stringify({ changed: result.changed, entry: result.config.plugins?.entries?.demo, allow: result.config.plugins?.allow, deny: result.config.plugins?.deny, slots: result.config.plugins?.slots, installPreserved: Boolean(result.config.plugins?.installs?.demo), outcome: result.outcomes[0]?.status }, null, 2)); })();"
  • Evidence after fix:
{
  "changed": true,
  "entry": {
    "enabled": false
  },
  "allow": [
    "keep"
  ],
  "deny": [
    "blocked"
  ],
  "slots": {
    "memory": "memory-core",
    "contextEngine": "legacy"
  },
  "installPreserved": true,
  "outcome": "skipped"
}
  • Observed result after fix: the failed-update disable path disables the plugin entry, removes stale allow/deny references, resets both selected slots to defaults, preserves the install record, and records the update as skipped.
  • What was not tested: a live beta update against the public npm registry and the specific third-party lossless-claw package from #81499.
  • Before evidence: source inspection on current main showed disablePluginConfigEntry() only set entries.<id>.enabled = false and did not touch allow/deny or slots.

Root Cause

  • Root cause: the failed-update disable helper only updated the plugin entry, unlike explicit uninstall config cleanup which already removes policy references and resets selected slots.
  • Missing detection / guardrail: no regression test covered disableOnFailure with a plugin selected in policy lists and plugin slots.
  • Contributing context: plugin update failure handling preserves install records so repair/reinstall remains possible, but dependent runtime config still needs to stop selecting the disabled plugin.

Regression Test Plan

  • Coverage level that should have caught this:
    • Unit test
  • Target test or file: src/plugins/update.test.ts
  • Scenario the test should lock in: an npm plugin update failure with disableOnFailure clears stale allow/deny references and resets selected memory/context-engine slots while preserving the install record.
  • Why this is the smallest reliable guardrail: the bug is pure config mutation in the update failure path, so a focused plugin update test covers the contract without registry access.
  • Existing related coverage: existing disable coverage checked the entry and install record only, not policy lists or slots.

User-visible / Behavior Changes

After an external plugin update failure disables a plugin, plugin policy and selected plugin slots are kept consistent with that disabled state. A context-engine plugin disabled during update now leaves the slot reset to legacy instead of continuing to point at the disabled plugin.

Diagram

Before:
plugin update failure -> entries.demo.enabled=false -> allow/deny/slots may still point at demo

After:
plugin update failure -> entries.demo.enabled=false -> allow/deny remove demo -> slots reset to defaults

Security Impact

  • 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
  • Risk + mitigation: N/A

Repro + Verification

Environment

  • OS: Windows
  • Runtime/container: local OpenClaw checkout, Node 24.14
  • Model/provider: N/A
  • Integration/channel: plugin update config path
  • Relevant config: synthetic plugin config with demo selected in allow, deny, slots.memory, and slots.contextEngine

Steps

  1. Run the local after-fix tsx proof above.
  2. Run the focused regression test for stale policy/slot cleanup.
  3. Run the adjacent existing disable regression test.
  4. Run formatting and diff checks.

Expected

  • Failed-update disable marks the plugin entry disabled.
  • Stale allow/deny references are removed.
  • Selected memory/context-engine slots reset to defaults.
  • The install record remains available for later repair.

Actual

  • Local proof produced entry.enabled=false, allow=["keep"], deny=["blocked"], slots.memory="memory-core", slots.contextEngine="legacy", installPreserved=true, and outcome="skipped".
  • Focused stale policy/slot regression test passed.
  • Existing disable regression test passed.
  • git diff --check and oxfmt passed.

Evidence

  • Trace/log snippets

Human Verification

  • Verified scenarios: failed-update disable cleans policy lists and resets memory / contextEngine slots while preserving the install record.
  • Edge cases checked: existing entry config is still preserved by the adjacent disable test.
  • What you did not verify: live third-party package update or public npm registry fallback behavior.

Review Conversations

  • Addressed bot review conversations: N/A
  • Unresolved conversations needing reviewer or maintainer judgment: N/A

Compatibility / Migration

  • Backward compatible? Yes
  • Config/env changes? No
  • Migration needed? No
  • Exact upgrade steps: N/A

Risks and Mitigations

  • Risk: resetting a selected slot during failed-update disable changes the active fallback sooner than before.
    • Mitigation: this only happens after OpenClaw has already disabled the plugin due to an update failure; resetting to the existing default prevents a stale selection from pointing at the disabled plugin.

Changed files

  • CHANGELOG.md (modified, +1/-0)
  • src/plugins/update.test.ts (modified, +58/-0)
  • src/plugins/update.ts (modified, +42/-3)

PR #81515: fix(cli): report stale plugin doctor config

Description (problem / solution / changelog)

Summary

  • Problem: openclaw plugins doctor could print stale plugin config warnings and still end with No plugin issues detected.
  • Why it matters: operators could read that final line as proof that plugin config was healthy, even when plugins.allow, plugins.entries, or plugins.slots.* still referenced a missing plugin.
  • What changed: plugins doctor now reuses the shared stale-plugin-config scanner, reports those findings under Plugin configuration:, and prints No plugin install-tree issues detected; configuration warnings remain. when only config findings exist.
  • What did NOT change (scope boundary): no plugin rollback, install/security scanner, cleanup, config mutation, JSON, or exit-code behavior changed.

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 #81499
  • This PR fixes a bug or regression

Real behavior proof (required for external PRs)

  • Behavior or issue addressed: stale plugin config no longer ends with the plain success line from openclaw plugins doctor.
  • Real environment tested: OpenClaw source checkout in the local OpenClaw PR container.
  • Exact steps or command run after this patch:
OPENCLAW_CONFIG_PATH=/workspace/openclaw/.tmp/openclaw-81499-proof/openclaw.json \
OPENCLAW_STATE_DIR=/workspace/openclaw/.tmp/openclaw-81499-proof/state \
pnpm openclaw plugins doctor
  • Evidence after fix:
Plugin configuration:
- plugins.allow: stale plugin reference "lossless-claw" was found.
- plugins.entries.lossless-claw: stale plugin reference "lossless-claw" was found.
- plugins.slots.contextEngine: slot references missing plugin "lossless-claw".
- Run "openclaw doctor --fix" to remove stale plugin ids and dangling channel references.

No plugin install-tree issues detected; configuration warnings remain.
  • Observed result after fix: the command reports actionable stale-config findings and does not print No plugin issues detected. when warnings remain.
  • What was not tested: plugin rollback, plugin install/update/uninstall paths, scanner policy changes, JSON output because plugins doctor has no JSON mode.
  • Before evidence (optional but encouraged): the same command path previously printed config warnings followed by No plugin issues detected.

Root Cause (if applicable)

  • Root cause: plugins doctor only counted runtime plugin load errors, manifest/discovery errors, source shadowing, and compatibility notices when deciding its final verdict.
  • Missing detection / guardrail: stale plugin config warnings already existed in the shared doctor scanner, but plugins doctor did not include them.
  • Contributing context (if known): the full CLI can warn from source config while runtime config has already normalized or ignored stale plugin references, so the scanner must inspect the config file source snapshot.

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: src/cli/plugins-cli.list.test.ts
  • Scenario the test should lock in: plugins.allow, plugins.entries.lossless-claw, and plugins.slots.contextEngine reference an unavailable lossless-claw plugin while runtime diagnostics are otherwise clean.
  • Why this is the smallest reliable guardrail: it exercises the plugins doctor command path and the real shared stale-config scanner without touching plugin install or cleanup behavior.
  • Existing test that already covers this (if any): src/commands/doctor/shared/stale-plugin-config.test.ts covers the scanner helper, but not the plugins doctor verdict.
  • If no new test is added, why not: N/A

User-visible / Behavior Changes

openclaw plugins doctor now reports stale plugin config references and distinguishes a healthy install tree from remaining config warnings.

Diagram (if applicable)

Before:
plugins doctor -> config warnings -> No plugin issues detected.

After:
plugins doctor -> plugin configuration findings -> install-tree-only summary

Security Impact (required)

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

Repro + Verification

Environment

  • OS: macOS host with OpenClaw PR container
  • Runtime/container: OpenClaw PR container via openclaw-shell
  • Model/provider: N/A
  • Integration/channel (if any): N/A
  • Relevant config (redacted):
{
  "plugins": {
    "allow": ["lossless-claw"],
    "entries": {
      "lossless-claw": {
        "enabled": true
      }
    },
    "slots": {
      "contextEngine": "lossless-claw"
    }
  }
}

Steps

  1. Create the isolated config above.
  2. Run pnpm openclaw plugins doctor with OPENCLAW_CONFIG_PATH and OPENCLAW_STATE_DIR pointed at the isolated temp paths.
  3. Inspect the final doctor output.

Expected

  • Stale plugin config is reported as plugin doctor findings.
  • The command does not end with plain No plugin issues detected. while config warnings remain.

Actual

  • Matches expected.

Evidence

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

Human Verification (required)

What you personally verified (not just CI), and how:

  • Verified scenarios: focused Vitest coverage for plugins doctor; real pnpm openclaw plugins doctor output with a stale lossless-claw config.
  • Edge cases checked: healthy command output remains No plugin issues detected.; source-config scanner catches stale refs even when runtime config is sanitized.
  • What you did not verify: plugin rollback, install/update/uninstall, security scanner behavior, config cleanup mutation, exit-code changes.

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/No): Yes
  • Config/env changes? (Yes/No): No
  • Migration needed? (Yes/No): No
  • If yes, exact upgrade steps: N/A

Risks and Mitigations

  • Risk: plugins doctor now does one additional config snapshot read and stale-config scan.
    • Mitigation: reuses existing doctor scanner and keeps behavior read-only.

Validation

  • pnpm run docs:list: pass
  • pnpm test src/cli/plugins-cli.list.test.ts src/commands/doctor/shared/stale-plugin-config.test.ts: pass
  • pnpm exec oxfmt --check src/cli/plugins-cli.ts src/cli/plugins-cli.list.test.ts docs/cli/plugins.md: pass
  • pnpm exec oxlint src/cli/plugins-cli.ts src/cli/plugins-cli.list.test.ts: pass
  • pnpm tsgo: pass
  • git diff --check: pass
  • pnpm check:changed: fails in unrelated all-project typecheck on src/plugins/registry.runtime-config.test.ts:45 and :46; those files are outside this PR diff.

Changed files

  • CHANGELOG.md (modified, +1/-0)
  • docs/cli/plugins.md (modified, +1/-1)
  • src/cli/plugins-cli.list.test.ts (modified, +56/-1)
  • src/cli/plugins-cli.ts (modified, +33/-7)

Code Example

openclaw update --channel beta --tag 2026.5.12-beta.5 --yes --timeout 1800

---

Could not check lossless-claw before update; falling back to installer path: Package not found on npm: @martian-engineering/lossless-claw@beta.
Plugin "lossless-claw" has no beta npm release for @martian-engineering/lossless-claw@beta; using @martian-engineering/lossless-claw@latest instead. Core update can still complete.
WARNING: Plugin "lossless-claw" installed tree contains dangerous code patterns: Shell command execution detected (child_process); Dynamic code execution detected; Environment variable access combined with network send.
Disabled "lossless-claw" after plugin update failure; OpenClaw will continue without it.

---

Config warnings:
- plugins.entries.lossless-claw: plugin not found: lossless-claw (stale config entry ignored; remove it from plugins config)
- plugins.allow: plugin not found: lossless-claw (stale config entry ignored; remove it from plugins config)

Doctor:
- plugins.slots.contextEngine: slot references missing plugin "lossless-claw"

---

[context-engine] Context engine "lossless-claw" is not registered; falling back to default engine "legacy".

---

No plugin issues detected.
RAW_BUFFERClick to expand / collapse

Summary

During a 2026.5.12-beta.4 -> 2026.5.12-beta.5 update on one macOS npm/pnpm install, configured external plugin lossless-claw had no @beta release, so the updater fell back to @latest. The beta 5 plugin scanner then blocked the installed tree for dangerous patterns in transitive dependency/example files, disabled the plugin, and left stale config references including the configured contextEngine slot.

Core OpenClaw remained healthy after update, but the host lost its configured context engine and now falls back to legacy with stale plugin config warnings.

Environment

  • OpenClaw before: 2026.5.12-beta.4
  • OpenClaw after: 2026.5.12-beta.5 (2cdd69a)
  • Install mode/root: npm/pnpm global install under Homebrew Node prefix
  • OS: macOS
  • Update command:
openclaw update --channel beta --tag 2026.5.12-beta.5 --yes --timeout 1800

Hostnames, usernames, local paths, account IDs, and tokens are intentionally omitted.

What happened

The update completed the core package upgrade, but plugin update output included:

Could not check lossless-claw before update; falling back to installer path: Package not found on npm: @martian-engineering/lossless-claw@beta.
Plugin "lossless-claw" has no beta npm release for @martian-engineering/lossless-claw@beta; using @martian-engineering/lossless-claw@latest instead. Core update can still complete.
WARNING: Plugin "lossless-claw" installed tree contains dangerous code patterns: Shell command execution detected (child_process); Dynamic code execution detected; Environment variable access combined with network send.
Disabled "lossless-claw" after plugin update failure; OpenClaw will continue without it.

After update, config and doctor output showed stale references:

Config warnings:
- plugins.entries.lossless-claw: plugin not found: lossless-claw (stale config entry ignored; remove it from plugins config)
- plugins.allow: plugin not found: lossless-claw (stale config entry ignored; remove it from plugins config)

Doctor:
- plugins.slots.contextEngine: slot references missing plugin "lossless-claw"

Runtime logs also confirmed fallback away from the configured context engine:

[context-engine] Context engine "lossless-claw" is not registered; falling back to default engine "legacy".

openclaw plugins doctor printed the stale config warnings, but still ended with:

No plugin issues detected.

Expected behavior

If a channel-specific plugin install falls back to @latest and the security scanner blocks the resulting tree, the updater should avoid leaving the host in a half-disabled/stale-config state. Possible acceptable outcomes:

  • Keep or restore the previously working plugin version if it was already installed and passed prior validation.
  • Disable the plugin but atomically clean or rewrite dependent config such as plugins.allow, plugins.entries, and plugins.slots.contextEngine.
  • Leave config untouched but emit a high-signal remediation summary that clearly says the context engine was disabled and what command/operator action is needed next.

The scanner may be correct to block this install; the bug is the confusing post-update state and stale context-engine configuration.

Actual post-update state

Healthy:

  • openclaw --version: OpenClaw 2026.5.12-beta.5 (2cdd69a)
  • openclaw gateway status --deep: LaunchAgent loaded, gateway running, CLI and gateway both beta 5, connectivity probe OK
  • Direct agent check through openai/gpt-5.5 / agentHarnessId: codex passed with fallbackUsed: false

Regressed/degraded:

  • lossless-claw absent from selected plugins after update
  • stale plugins.entries.lossless-claw
  • stale plugins.allow reference
  • plugins.slots.contextEngine still points at missing plugin
  • runtime falls back to legacy context engine
  • plugins doctor still says No plugin issues detected after printing related warnings

Likely source areas

  • src/plugins/update.ts
  • src/plugins/install-security-scan.runtime.ts
  • src/plugins/config-activation-shared.ts
  • src/plugins/effective-plugin-ids.ts
  • src/plugins/slots.ts
  • context engine registration/fallback path

Not treated as failures

  • Existing task-audit warnings on the host predated beta 5.
  • Optional model-pricing warnings did not block model routing.
  • I did not force reinstall the plugin or run openclaw doctor --fix, because either would mutate the operator state beyond update/audit verification.

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

If a channel-specific plugin install falls back to @latest and the security scanner blocks the resulting tree, the updater should avoid leaving the host in a half-disabled/stale-config state. Possible acceptable outcomes:

  • Keep or restore the previously working plugin version if it was already installed and passed prior validation.
  • Disable the plugin but atomically clean or rewrite dependent config such as plugins.allow, plugins.entries, and plugins.slots.contextEngine.
  • Leave config untouched but emit a high-signal remediation summary that clearly says the context engine was disabled and what command/operator action is needed next.

The scanner may be correct to block this install; the bug is the confusing post-update state and stale context-engine configuration.

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 v2026.5.12-beta.5 plugin update disables lossless-claw after @beta fallback and leaves stale contextEngine config [2 pull requests, 1 comments, 2 participants]