openclaw - ✅(Solved) Fix CLI `openclaw status` text mode extremely slow (~20-30s) due to `cache: false` hardcoded in manifest registry loader [1 pull requests, 2 comments, 3 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#73291Fetched 2026-04-29 06:21:24
View on GitHub
Comments
2
Participants
3
Timeline
5
Reactions
0
Timeline (top)
commented ×2closed ×1cross-referenced ×1renamed ×1

Root Cause

The root cause is not JSON5 parsing speed per se — it's that the manifest registry cache is hardcoded disabled.

The Smoking Gun

File: dist/manifest-registry-installed-BaIMBgdv.js:64

return loadPluginManifestRegistry({
    config: params.config,
    workspaceDir: params.workspaceDir,
    env: params.env,
    cache: false,  // ← THIS IS THE BUG
    candidates,
    diagnostics: [...diagnostics],
    installRecords: extractPluginInstallRecordsFromInstalledPluginIndex(params.index)
});

The cache is hardcoded to false. The existing cache infrastructure (1-second TTL, mtime-based invalidation) at dist/manifest-registry-BeaRFaM3.js:113 is completely bypassed.

Full Call Chain (Text Mode)

openclaw status (text)
  → dist/status-faD5DC8z.js:runDaemonStatus()
    → dist/status-faD5DC8z.js:printDaemonStatus() [opts.json = false]
      → (text formatter path loads)
      → dist/status-BW3nLVAj.js:buildPluginRegistrySnapshotReport():174
        → dist/manifest-registry-installed-BaIMBgdv.js:loadPluginManifestRegistryForInstalledIndex()
          → dist/manifest-registry-BeaRFaM3.js:loadPluginManifestRegistry({ cache: false }):317
            → discoverOpenClawPlugins() in dist/discovery-IHhcAvkF.js:695
              → For each of 112 plugins:
                → loadPluginManifest() in dist/manifest-C0Wa8IEc.js:1013
                  → JSON5.parse() in dist/manifest-C0Wa8IEc.js:1036

Why JSON Mode Is Fast

// dist/status-faD5DC8z.js:printDaemonStatus()
if (opts.json) {
    const sanitized = sanitizeDaemonStatusForJson(status);
    defaultRuntime.writeJson(sanitized);
    return;  // ← Early return, text formatter NEVER loaded
}

JSON mode never loads status-BW3nLVAj.js, so it never calls buildPluginRegistrySnapshotReport(), so it never triggers manifest parsing.

Cache Infrastructure Already Exists

// dist/manifest-registry-BeaRFaM3.js:113
const DEFAULT_MANIFEST_CACHE_MS = 1e3;  // 1 second TTL

// dist/manifest-registry-BeaRFaM3.js:317-324
const cacheEnabled = params.cache !== false && !params.installRecords && shouldUseManifestCache(env);
if (cacheEnabled) {
    const cached = registryCache.get(cacheKey);
    if (cached && cached.expiresAt > Date.now()) return cached.registry;
}

The cache works. It's just never enabled because cache: false is passed.

Fix Action

Workaround

Use openclaw status --json --timeout 3000 or openclaw channels status for quick checks.

PR fix notes

PR #73410: fix(plugins): enable metadata snapshot cache for status diagnostics

Description (problem / solution / changelog)

fix(plugins): enable metadata snapshot cache for status diagnostics

Summary

Fixes #73291.

This PR enables plugin metadata snapshot caching (default 1 second TTL) for validate-mode metadata loads used by status diagnostics, reducing repeated manifest discovery/parse work during openclaw status text-mode scans.

Issue Evidence Is Clear

  • Issue report shows openclaw status text mode taking ~20-30s while --json is much faster.
  • Shared evidence includes high sync filesystem activity (statx / realpathSync storms) and heavy manifest parse stacks.
  • Code-path verification in this branch confirms text-mode status performs plugin compatibility snapshot loading, which previously forced cache: false in metadata snapshot loads.
  • Linked issue: https://github.com/openclaw/openclaw/issues/73291

What Changed

  • Updated src/plugins/runtime/metadata-registry-loader.ts
    • Changed metadata snapshot load option from cache: false to cache: true.
    • Keeps behavior read-only (activate: false, mode: "validate"), only allowing short-lived manifest/discovery cache reuse.
  • Updated src/plugins/runtime/metadata-registry-loader.test.ts
    • Updated expectation to assert cache: true.

Why This Small Fix

  • Uses existing cache implementation and defaults (1 second TTL) with no new flags or config surface.
  • Keeps blast radius minimal and aligned with issue request for a low-cost, practical fix.
  • Accepts tiny short-window staleness in diagnostics for significantly lower repeated filesystem/manifest overhead.

Validation

  • pnpm docs:list
  • pnpm test src/plugins/runtime/metadata-registry-loader.test.ts

Risk

  • Very low: metadata may be up to ~1 second stale in read-only diagnostics paths.
  • No activation/runtime behavior changes; only snapshot cache policy changed.

AI-assisted

  • AI-assisted and manually reviewed

Changed files

  • src/plugins/runtime/metadata-registry-loader.test.ts (modified, +1/-1)
  • src/plugins/runtime/metadata-registry-loader.ts (modified, +1/-1)

Code Example

return loadPluginManifestRegistry({
    config: params.config,
    workspaceDir: params.workspaceDir,
    env: params.env,
    cache: false,  // ← THIS IS THE BUG
    candidates,
    diagnostics: [...diagnostics],
    installRecords: extractPluginInstallRecordsFromInstalledPluginIndex(params.index)
});

---

openclaw status (text)
  → dist/status-faD5DC8z.js:runDaemonStatus()
    → dist/status-faD5DC8z.js:printDaemonStatus() [opts.json = false]
       (text formatter path loads)
      → dist/status-BW3nLVAj.js:buildPluginRegistrySnapshotReport():174
        → dist/manifest-registry-installed-BaIMBgdv.js:loadPluginManifestRegistryForInstalledIndex()
          → dist/manifest-registry-BeaRFaM3.js:loadPluginManifestRegistry({ cache: false }):317
discoverOpenClawPlugins() in dist/discovery-IHhcAvkF.js:695
For each of 112 plugins:
loadPluginManifest() in dist/manifest-C0Wa8IEc.js:1013
JSON5.parse() in dist/manifest-C0Wa8IEc.js:1036

---

// dist/status-faD5DC8z.js:printDaemonStatus()
if (opts.json) {
    const sanitized = sanitizeDaemonStatusForJson(status);
    defaultRuntime.writeJson(sanitized);
    return;  // ← Early return, text formatter NEVER loaded
}

---

// dist/manifest-registry-BeaRFaM3.js:113
const DEFAULT_MANIFEST_CACHE_MS = 1e3;  // 1 second TTL

// dist/manifest-registry-BeaRFaM3.js:317-324
const cacheEnabled = params.cache !== false && !params.installRecords && shouldUseManifestCache(env);
if (cacheEnabled) {
    const cached = registryCache.get(cacheKey);
    if (cached && cached.expiresAt > Date.now()) return cached.registry;
}

---

# Text mode — ~20-30s, 0 bytes output for most of it
$ time openclaw status
# JSON mode — ~8s
$ time openclaw status --json --timeout 3000
# channels status — ~2s (skips plugin diagnostics)
$ time openclaw channels status
# usage — ~2s (skips plugin diagnostics)
$ time openclaw status --usage
RAW_BUFFERClick to expand / collapse

Bug Report

Environment

  • OpenClaw version: 2026.4.25
  • Node.js: v24.14.1
  • OS: Ubuntu 24.04 LTS
  • Installed plugins: 112 (19 enabled, 93 disabled)

Problem

openclaw status in text mode takes 20-30 seconds to produce output, appearing to hang. JSON mode (--json) completes in ~8 seconds. The process writes 0 bytes to stdout for the entire duration.

Evidence

  1. strace shows 48K statx filesystem calls in 3 seconds — the CLI scans all 112 plugin directories
  2. V8 profiler shows 15%+ CPU in json5.parse():
    • json5/lib/parse.js:13 — 977 ticks (4.4%)
    • json5/lib/parse.js:133 — 906 ticks (4.1%)
    • json5/lib/parse.js:570 — 664 ticks (3.0%)
  3. 112 plugin manifests found at dist/extensions/*/openclaw.plugin.json
  4. Text mode eventually completes after ~20-30s (not an infinite hang)

Root Cause

The root cause is not JSON5 parsing speed per se — it's that the manifest registry cache is hardcoded disabled.

The Smoking Gun

File: dist/manifest-registry-installed-BaIMBgdv.js:64

return loadPluginManifestRegistry({
    config: params.config,
    workspaceDir: params.workspaceDir,
    env: params.env,
    cache: false,  // ← THIS IS THE BUG
    candidates,
    diagnostics: [...diagnostics],
    installRecords: extractPluginInstallRecordsFromInstalledPluginIndex(params.index)
});

The cache is hardcoded to false. The existing cache infrastructure (1-second TTL, mtime-based invalidation) at dist/manifest-registry-BeaRFaM3.js:113 is completely bypassed.

Full Call Chain (Text Mode)

openclaw status (text)
  → dist/status-faD5DC8z.js:runDaemonStatus()
    → dist/status-faD5DC8z.js:printDaemonStatus() [opts.json = false]
      → (text formatter path loads)
      → dist/status-BW3nLVAj.js:buildPluginRegistrySnapshotReport():174
        → dist/manifest-registry-installed-BaIMBgdv.js:loadPluginManifestRegistryForInstalledIndex()
          → dist/manifest-registry-BeaRFaM3.js:loadPluginManifestRegistry({ cache: false }):317
            → discoverOpenClawPlugins() in dist/discovery-IHhcAvkF.js:695
              → For each of 112 plugins:
                → loadPluginManifest() in dist/manifest-C0Wa8IEc.js:1013
                  → JSON5.parse() in dist/manifest-C0Wa8IEc.js:1036

Why JSON Mode Is Fast

// dist/status-faD5DC8z.js:printDaemonStatus()
if (opts.json) {
    const sanitized = sanitizeDaemonStatusForJson(status);
    defaultRuntime.writeJson(sanitized);
    return;  // ← Early return, text formatter NEVER loaded
}

JSON mode never loads status-BW3nLVAj.js, so it never calls buildPluginRegistrySnapshotReport(), so it never triggers manifest parsing.

Cache Infrastructure Already Exists

// dist/manifest-registry-BeaRFaM3.js:113
const DEFAULT_MANIFEST_CACHE_MS = 1e3;  // 1 second TTL

// dist/manifest-registry-BeaRFaM3.js:317-324
const cacheEnabled = params.cache !== false && !params.installRecords && shouldUseManifestCache(env);
if (cacheEnabled) {
    const cached = registryCache.get(cacheKey);
    if (cached && cached.expiresAt > Date.now()) return cached.registry;
}

The cache works. It's just never enabled because cache: false is passed.

Reproduction

# Text mode — ~20-30s, 0 bytes output for most of it
$ time openclaw status
# JSON mode — ~8s
$ time openclaw status --json --timeout 3000
# channels status — ~2s (skips plugin diagnostics)
$ time openclaw channels status
# usage — ~2s (skips plugin diagnostics)
$ time openclaw status --usage

Suggested Fix

Option A (one-line): Change cache: false to cache: true in manifest-registry-installed-BaIMBgdv.js:64.

Option B (slightly better): Add cache parameter to loadPluginManifestRegistryForInstalledIndex() so callers can opt-in, and have status pass cache: true.

Option A is probably sufficient — the cache TTL is only 1 second, so stale data is minimal.

Workaround

Use openclaw status --json --timeout 3000 or openclaw channels status for quick checks.

extent analysis

TL;DR

Enable the manifest registry cache by changing cache: false to cache: true in manifest-registry-installed-BaIMBgdv.js:64 to fix the performance issue with openclaw status in text mode.

Guidance

  • Identify the line of code where the cache is hardcoded to false and consider changing it to true to enable caching.
  • Review the call chain to understand how the cache parameter is passed through different functions and how it affects the performance.
  • Consider adding a cache parameter to loadPluginManifestRegistryForInstalledIndex() to allow callers to opt-in to caching.
  • Use the workaround openclaw status --json --timeout 3000 or openclaw channels status for quick checks until the fix is implemented.

Example

// dist/manifest-registry-installed-BaIMBgdv.js:64
return loadPluginManifestRegistry({
    config: params.config,
    workspaceDir: params.workspaceDir,
    env: params.env,
    cache: true,  // Enable caching
    candidates,
    diagnostics: [...diagnostics],
    installRecords: extractPluginInstallRecordsFromInstalledPluginIndex(params.index)
});

Notes

The cache infrastructure already exists and has a 1-second TTL, so enabling caching should not introduce significant staleness issues. However, it's essential to review the code and consider the implications of caching on the overall system.

Recommendation

Apply the workaround openclaw status --json --timeout 3000 or openclaw channels status for quick checks until the fix is implemented, and then enable the manifest registry cache by changing cache: false to cache: true in manifest-registry-installed-BaIMBgdv.js:64 to fix the performance 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

openclaw - ✅(Solved) Fix CLI `openclaw status` text mode extremely slow (~20-30s) due to `cache: false` hardcoded in manifest registry loader [1 pull requests, 2 comments, 3 participants]