openclaw - 💡(How to fix) Fix [Bug]: plugin manifest loader uses JSON5.parse for plain JSON files (~3x slower gateway boot) [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#73011Fetched 2026-04-28 06:28:42
View on GitHub
Comments
2
Participants
3
Timeline
3
Reactions
1
Author
Timeline (top)
commented ×2closed ×1

Plugin manifests are parsed with JSON5.parse. On this Pi that path runs ~10x slower than JSON.parse. With ~60+ plugins, the gateway spends 2-3 minutes parsing manifests on every boot. None of the bundled manifests on this install use JSON5-specific syntax.

Error Message

let raw; try { raw = JSON5.parse(fs.readFileSync(opened.fd, "utf-8")); } catch (err) { return { ok: false, error: ... }; }

Root Cause

Plugin manifests are parsed with JSON5.parse. On this Pi that path runs ~10x slower than JSON.parse. With ~60+ plugins, the gateway spends 2-3 minutes parsing manifests on every boot. None of the bundled manifests on this install use JSON5-specific syntax.

Fix Action

Fix / Workaround

3x faster restart-to-channels-up after the patch.

I patched this on my box by replacing the JSON5.parse(...) call with a try-JSON.parse-first-then-JSON5.parse block. Two-line change in loadPluginManifest. Confirmed via wall-time and via --prof (json5 functions dropped out of the top 30 in the post-fix profile).

Code Example

let raw;
try {
    raw = JSON5.parse(fs.readFileSync(opened.fd, "utf-8"));
} catch (err) {
    return { ok: false, error: ... };
}

---

ticks  total  nonlib   name
  23337   8.5%   23.1%  JS: *default  json5/lib/parse.js:133:13   (entry point)
  22074   8.0%   21.8%  JS: *parse    json5/lib/parse.js:13:33    (parser core)
  14929   5.4%   14.8%  JS: *string   json5/lib/parse.js:570:12   (string token reader)
   1237   0.5%    1.2%  JS: *value    json5/lib/parse.js:238:11
   1145   0.4%    1.1%  JS: *read     json5/lib/parse.js:113:15
    282   0.1%    0.3%  JS: *loadPluginManifest  manifest-C0Wa8IEc.js:1013:28
    150   0.1%    0.1%  JS: *loadPluginManifestRegistry  manifest-registry-BeaRFaM3.js:317:36
    197   0.1%    0.2%  JS: *buildRecord  manifest-registry-BeaRFaM3.js:174:21
RAW_BUFFERClick to expand / collapse

Bug type

Bug (loadPluginManifest parses every plugin manifest with JSON5.parse, which is much slower than native JSON.parse and the manifests don't use any JSON5-specific syntax)

Beta release blocker

No

Summary

Plugin manifests are parsed with JSON5.parse. On this Pi that path runs ~10x slower than JSON.parse. With ~60+ plugins, the gateway spends 2-3 minutes parsing manifests on every boot. None of the bundled manifests on this install use JSON5-specific syntax.

Steps to reproduce

  1. Run openclaw 2026.4.25
  2. Restart the gateway
  3. Watch the time gap from [gateway] ready to [whatsapp] Listening for personal WhatsApp inbound messages.

Expected behaviour

loadPluginManifest() should try the native JSON.parse first and fall back to JSON5.parse only if the file actually uses JSON5-specific syntax. Most manifests will go the fast path and skip JSON5 entirely.

Actual behaviour

dist/manifest-*.js loadPluginManifest() body:

let raw;
try {
    raw = JSON5.parse(fs.readFileSync(opened.fd, "utf-8"));
} catch (err) {
    return { ok: false, error: ... };
}

Every plugin manifest goes through the JSON5 parser regardless of content. The cost dominates gateway boot on slower hardware.

OpenClaw version

2026.4.25

Environment

Raspberry Pi 500 (Debian Trixie, aarch64). Gateway runs as a systemd user service. ~60+ bundled plugin manifests under dist/extensions/<plugin>/openclaw.plugin.json.

Logs, screenshots, and evidence

V8 --prof capture across a 4m28s [gateway] ready -> channels-up window. Top hot JavaScript functions:

   ticks  total  nonlib   name
  23337   8.5%   23.1%  JS: *default  json5/lib/parse.js:133:13   (entry point)
  22074   8.0%   21.8%  JS: *parse    json5/lib/parse.js:13:33    (parser core)
  14929   5.4%   14.8%  JS: *string   json5/lib/parse.js:570:12   (string token reader)
   1237   0.5%    1.2%  JS: *value    json5/lib/parse.js:238:11
   1145   0.4%    1.1%  JS: *read     json5/lib/parse.js:113:15
    282   0.1%    0.3%  JS: *loadPluginManifest  manifest-C0Wa8IEc.js:1013:28
    150   0.1%    0.1%  JS: *loadPluginManifestRegistry  manifest-registry-BeaRFaM3.js:317:36
    197   0.1%    0.2%  JS: *buildRecord  manifest-registry-BeaRFaM3.js:174:21

Combined, the json5 parse functions account for ~52% of all non-shared-library JavaScript CPU time. The rest of the profile is normal startup work (path resolution, module imports, etc.).

C++ side reflects the same pattern - lots of access() (file existence checks), getdents64 (directory enumeration), __open64_nocancel (manifest opens). Consistent with mass manifest scanning.

Wall-time impact on this install:

PhasePre-fixPost-fix
[gateway] ready (boot)18.4s10.8s
Ready -> [whatsapp] Listening (channels)4m28s1m23s
Total restart -> channels up4m46s1m34s

3x faster restart-to-channels-up after the patch.

Code pointers on this install:

  • dist/manifest-C0Wa8IEc.js line 1036, loadPluginManifest() body, single JSON5.parse(...) call

Bundle filename will rotate per release; grep for JSON5.parse(fs.readFileSync(opened.fd.

Impact and severity

Affected: every gateway restart, and every CLI command that triggers the registry load (most of them on this install - boot-check, message send, cron list etc.). The slower the hardware, the bigger the slowdown; on a fast desktop machine it might be barely noticeable.

Severity: high on slow hardware (Pi class machines, low-end VPS), low on fast hardware. The 3x speedup is independent of CPU contention - even at nice +10 with no other processes competing, the same 3x gap exists.

Frequency: every gateway boot and every CLI command.

Additional information

I patched this on my box by replacing the JSON5.parse(...) call with a try-JSON.parse-first-then-JSON5.parse block. Two-line change in loadPluginManifest. Confirmed via wall-time and via --prof (json5 functions dropped out of the top 30 in the post-fix profile).

If any bundled manifest does need JSON5-specific syntax for a future feature, the fallback handles it. If none ever do, the JSON5 dep could be removed from the manifest loader entirely.

extent analysis

TL;DR

Try replacing the JSON5.parse() call with a try-JSON.parse-first-then-JSON5.parse block in the loadPluginManifest() function to improve performance.

Guidance

  • Identify the loadPluginManifest() function in the codebase and locate the JSON5.parse() call.
  • Replace the JSON5.parse() call with a try-catch block that attempts to parse the JSON using JSON.parse() first, and falls back to JSON5.parse() if JSON.parse() fails.
  • Verify the change by measuring the time it takes for the gateway to boot and for channels to come up after the patch.
  • Consider removing the JSON5 dependency from the manifest loader if no bundled manifests require JSON5-specific syntax.

Example

let raw;
try {
    raw = JSON.parse(fs.readFileSync(opened.fd, "utf-8"));
} catch (err) {
    try {
        raw = JSON5.parse(fs.readFileSync(opened.fd, "utf-8"));
    } catch (err) {
        return { ok: false, error: ... };
    }
}

Notes

The proposed change assumes that most plugin manifests do not require JSON5-specific syntax. If any manifests do require JSON5 syntax, the fallback to JSON5.parse() will ensure they are still parsed correctly.

Recommendation

Apply the workaround by replacing the JSON5.parse() call with a try-JSON.parse-first-then-JSON5.parse block, as this has been shown to provide a significant performance improvement.

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 [Bug]: plugin manifest loader uses JSON5.parse for plain JSON files (~3x slower gateway boot) [2 comments, 3 participants]