Skip to content

[Bug] Stale plugin-runtime-deps causes Gateway crash-loop after openclaw update #73520

@kingkong9817

Description

@kingkong9817

Bug: Stale plugin-runtime-deps directory causes Gateway crash-loop after openclaw update

Version Info

  • Before: 2026.4.24
  • After: 2026.4.26
  • OS: macOS 26.4.1 (arm64), Node 25.9.0
  • Install: npm global (openclaw update)

Symptom

After running openclaw update, Gateway crashes and enters a launchd crash-loop for 5 hours, with no logs produced by the new process. Recovery required manually removing the old plugin-runtime-deps directory.

Root Cause (detailed data)

Timeline:

Time (GMT+8) Event
13:08 openclaw update runs, npm installs 2026.4.26
13:10:25 Old Gateway process (v2026.4.24) receives SIGTERM
13:10:26 Old process reloads config, discovers bundled feishu/whatsapp plugins require >=2026.4.25 → version check fails → shutdown error
13:10 ~ 18:12 launchd repeatedly restarts new Gateway binary → process crashes before reaching logger output → launchd throttle puts it on ice for 5 hours
18:12 Manual gateway stop → mv old runtime-deps → gateway start → recovered

Two-layer failure:

  1. Old process version check failure: After update, the still-running v2026.4.24 Gateway reloads config, finds bundled feishu/whatsapp plugins from 2026.4.26 that require >=2026.4.25, but the running host is 2026.4.24 → fatal config error → exit.

  2. New process crashes due to stale runtime-deps (the core bug): launchd starts the new v2026.4.26 binary, but plugin-runtime-deps/ now contains three directories:

    openclaw-2026.4.24-da6bdffc3d96/  ← old, 4009 JS files, full core code
    openclaw-2026.4.26-da6bdffc3d96/  ← new core deps, 3621 JS files
    openclaw-unknown-bd1f0b6280a9/    ← new channel layer deps, 3509 JS files
    
    • Lexicographic ordering: 2026.4.24 < 2026.4.26, so the old directory is scanned first
    • The old directory has no package.json (runtime-deps only have .openclaw-runtime-deps.json), but its dist/ contains the full OpenClaw core modules (min-host-version, version, etc.)
    • 2026.4.26 introduced a layered runtime-deps architecture (previously a single flat directory), but openclaw update doesn't clean up the old format directory
    • The new Gateway binary scans the old dist/ during startup → module loading conflict → crash at Node.js initialization stage, before the logger is even available

Evidence:

  • gateway.err.log jumps directly from 13:10:26 to 18:12:36 — no new process logs in between
  • macOS launchd shows runs = 2 (processes that exit within 10 seconds are classified as crashes, not counted as normal runs)
  • Manually removing the old directory immediately resolved the issue
  • Old and new dist/ directories have many identically-named but different JS files (e.g., min-host-version-xxx.js, version-xxx.js)

Proposed Fix

Add automatic cleanup to the openclaw update flow:

  1. After npm install completes, scan plugin-runtime-deps/
  2. Recognize directory naming pattern openclaw-{version}-{hash} or openclaw-unknown-{hash}
  3. Call resolveBinaryVersion() to get the current installed version
  4. Remove directories whose version doesn't match (keep openclaw-unknown-*)
  5. Log which directories were cleaned up
  6. Perform a hard restart (not old-process reload) to ensure the new binary starts fresh

Pseudo-code:

async function cleanupOldRuntimeDeps(currentVersion: string) {
  const depsDir = path.join(configDir, 'plugin-runtime-deps');
  const entries = await fs.readdir(depsDir);
  
  for (const entry of entries) {
    const match = entry.match(/^openclaw-(\d+\.\d+\.\d+)-/);
    if (match && match[1] !== currentVersion) {
      const fullPath = path.join(depsDir, entry);
      await fs.rm(fullPath, { recursive: true });
      log.info(`[update] cleaned up old runtime deps: ${entry}`);
    }
  }
}

Temporary Workaround

openclaw gateway stop
find ~/.openclaw/plugin-runtime-deps/ -maxdepth 1 -type d \
  -name "openclaw-*" ! -name "openclaw-$(openclaw --version | grep -oE '\d+\.\d+\.\d+')-*" \
  ! -name "openclaw-unknown-*" -exec rm -rf {} \;
openclaw gateway start

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions