Skip to content

fix: use JSON5 parser for plugin manifest loading (#57734) [AI-assisted]#59084

Merged
hxy91819 merged 4 commits into
openclaw:mainfrom
singleGanghood:fix/issue-57734-plugin-install-config-json
Apr 2, 2026
Merged

fix: use JSON5 parser for plugin manifest loading (#57734) [AI-assisted]#59084
hxy91819 merged 4 commits into
openclaw:mainfrom
singleGanghood:fix/issue-57734-plugin-install-config-json

Conversation

@singleGanghood

Copy link
Copy Markdown
Contributor

Plugin install fails when a third-party plugin manifest (openclaw.plugin.json)
contains JSON5 features such as trailing commas, comments, or unquoted keys.
The strict JSON.parse used in loadPluginManifest and loadBundleManifestRaw
rejects these files during the config validation step of writeConfigFile,
preventing the install from completing.

Summary

  • Problem: Installing @vectorize-io/hindsight-openclaw plugin fails with Config validation failed: plugins: plugin: failed to parse plugin manifest: SyntaxError: Expected double-quoted property name in JSON at position 8912. The plugin's openclaw.plugin.json manifest uses JSON5 features (trailing commas) that JSON.parse rejects.
  • Why it matters: Users cannot install any third-party plugin whose manifest uses JSON5 syntax. The existing config is safe (validation caught the error before writing), but the install is permanently blocked.
  • What changed: Replaced JSON.parse with JSON5.parse in loadPluginManifest (manifest.ts) and loadBundleManifestRaw (bundle-manifest.ts) so plugin manifests can contain trailing commas, comments, and unquoted keys — consistent with how the main config file (openclaw.json) is already parsed.
  • What did NOT change (scope boundary): Config file serialization (writeConfigFile) still uses strict JSON.stringify. Only the manifest reading path was changed. No changes to config validation logic, merge-patch, or env-preserve paths.

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

Root Cause / Regression History (if applicable)

  • Root cause: loadPluginManifest (manifest.ts L273) and loadBundleManifestRaw (bundle-manifest.ts L120) use JSON.parse to read openclaw.plugin.json files. This strict parser rejects JSON5 features (trailing commas, comments, unquoted keys) that third-party plugin authors may use. When writeConfigFile calls validateConfigObjectRawWithPlugins, the validation loads all registered plugin manifests — if any manifest fails to parse, the validation returns { ok: false } and the write throws, blocking plugin installation.
  • Missing detection / guardrail: No test coverage for JSON5 tolerance in plugin manifest loading. The main config file reader already uses JSON5.parse, but manifest loading was inconsistent.
  • Prior context: The config reader (io.ts) uses json5.parse for openclaw.json, but plugin manifests were always loaded with strict JSON.parse. This inconsistency was introduced when the plugin manifest system was first built and never corrected.
  • Why this regressed now: Not a regression — this has always been the behavior. It became visible when @vectorize-io/hindsight-openclaw (a popular memory plugin) shipped a manifest with trailing commas.
  • If unknown, what was ruled out: Initially investigated merge-patch, env-preserve, and JSON serialization paths — all ruled out as JSON.stringify cannot produce malformed JSON.

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/plugins/manifest.json5-tolerance.test.ts
  • Scenario the test should lock in: loadPluginManifest successfully parses manifests containing trailing commas, single-line comments, and unquoted property names.
  • Why this is the smallest reliable guardrail: Directly tests the exact function (loadPluginManifest) that failed, with the exact JSON5 features that caused the issue.
  • Existing test that already covers this (if any): None — manifest-registry.test.ts writes manifests via JSON.stringify (which never produces JSON5), so the JSON5 path was never exercised.

User-visible / Behavior Changes

  • Third-party plugins with JSON5 manifests (trailing commas, comments, unquoted keys) can now be installed successfully.
  • No change to existing plugin behavior — strict JSON manifests continue to work identically.

Diagram (if applicable)

Before:
  openclaw plugins install @vectorize-io/hindsight-openclaw
    → installPluginFromNpmSpec (OK)
    → persistPluginInstall
      → writeConfigFile
        → validateConfigObjectRawWithPlugins
          → loadPluginManifestRegistry
            → loadPluginManifest
              → JSON.parse(manifest) ← FAILS on trailing comma
        → throw Error("Config validation failed: ...")
    ❌ Installation blocked

After:
  openclaw plugins install @vectorize-io/hindsight-openclaw
    → installPluginFromNpmSpec (OK)
    → persistPluginInstall
      → writeConfigFile
        → validateConfigObjectRawWithPlugins
          → loadPluginManifestRegistry
            → loadPluginManifest
              → JSON5.parse(manifest) ← Tolerates trailing commas
        → validation passes
    → config written to disk
    ✅ Installation succeeds

Security Impact (required)

  • 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)

Repro + Verification

Environment

  • OS: Darwin 23.4.0 arm64
  • Runtime: Node.js v22.18.0, pnpm 10.28.0
  • Model/provider: N/A
  • Integration/channel: N/A
  • Relevant config: Default

Steps

  1. Run openclaw plugins install @vectorize-io/hindsight-openclaw
  2. Plugin downloads and extracts successfully
  3. Security warnings appear (expected)

Expected

  • Plugin installs successfully and config is updated

Actual (before fix)

  • Config validation failed: plugins: plugin: failed to parse plugin manifest: SyntaxError: Expected double-quoted property name in JSON at position 8912 (line 219 column 5)

Evidence

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

New test file manifest.json5-tolerance.test.ts passes 5/5 tests:

  • parses a standard JSON manifest without issues
  • parses a manifest with trailing commas
  • parses a manifest with single-line comments
  • parses a manifest with unquoted property names
  • still rejects completely invalid syntax

Existing tests: 101 tests across manifest-registry.test.ts, bundle-manifest.test.ts, install.test.ts, installs.test.ts, and io.write-config.test.ts all pass with zero regression.

Git hooks ran full pnpm check (tsgo + oxlint + conflict markers + webhook lint + auth lint) — all passed.

Human Verification (required)

  • Verified scenarios: AI verified via automated test suite (5 new + 101 existing tests). Manual verification of openclaw plugins install @vectorize-io/hindsight-openclaw requires the actual plugin package.
  • Edge cases checked: Completely invalid syntax still rejected; standard JSON still parsed correctly.
  • What you did NOT verify: Actual end-to-end install of @vectorize-io/hindsight-openclaw (requires npm access to the package and a live OpenClaw setup).

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)
  • Config/env changes? (No)
  • Migration needed? (No)

Risks and Mitigations

  • Risk: JSON5 is more permissive than JSON; a malformed manifest that happens to be valid JSON5 but semantically wrong could now be loaded instead of rejected.
    • Mitigation: The manifest is still validated structurally after parsing (required fields id, configSchema checked). JSON5 only affects syntax tolerance, not semantic validation. JSON5 is already a project dependency used for the main config file.

Files changed:

 src/plugins/bundle-manifest.ts                    | 3 ++-
 src/plugins/manifest.ts                           | 3 ++-
 src/plugins/manifest.json5-tolerance.test.ts      | 93 +++++++++++++++++++++
 3 files changed, 97 insertions(+), 2 deletions(-)

@greptile-apps

greptile-apps Bot commented Apr 1, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes a real plugin installation failure by replacing JSON.parse with JSON5.parse in the two manifest-loading functions (loadPluginManifest in manifest.ts and loadBundleManifestFile in bundle-manifest.ts), matching the JSON5-tolerant parsing already used for the main openclaw.json config file. json5 is already a project dependency and the fix is fully backward-compatible (all valid JSON is valid JSON5).

Key changes:

  • src/plugins/manifest.ts: JSON.parseJSON5.parse in loadPluginManifest (the direct cause of the reported failure).
  • src/plugins/bundle-manifest.ts: Same one-line fix in loadBundleManifestFile for consistency.
  • src/plugins/manifest.json5-tolerance.test.ts: New test file with 5 focused test cases covering standard JSON, trailing commas, single-line comments, unquoted keys, and invalid-syntax rejection.

The scope is precisely right — only the reading path is touched; serialization (JSON.stringify) and all validation logic are unchanged.

Confidence Score: 5/5

Safe to merge — minimal, backward-compatible fix using an existing dependency, well-tested, and tightly scoped.

All findings are P2 (a minor test-coverage suggestion). The production code change is a single-line substitution in each of two files, using a library already present in the dependency tree and already used for the main config reader. No serialization, validation, or auth paths are touched.

No files require special attention. The bundle-manifest.ts change is not directly covered by the new test file, but it is an identical pattern to the manifest.ts change and is covered by existing bundle-manifest tests.

Prompt To Fix All With AI
This is a comment left during a code review.
Path: src/plugins/manifest.json5-tolerance.test.ts
Line: 84

Comment:
**Weak "invalid syntax" fixture may pass for wrong reasons**

The string `"not json at all {{{}}"` is rejected by both `JSON.parse` and `JSON5.parse`, so it correctly tests the error path. However, since JSON5 is more permissive, it might be worth adding a fixture that is *valid* JSON5 but *structurally* invalid (e.g. parses to a non-object like `"just a string"` or `42`), to ensure the `isRecord` / structural-validation path also stays exercised under JSON5.

This is a suggestion to improve test coverage completeness, not a bug.

How can I resolve this? If you propose a fix, please make it concise.

Reviews (1): Last reviewed commit: "fix: use JSON5 parser for plugin manifes..." | Re-trigger Greptile

Comment thread src/plugins/manifest.json5-tolerance.test.ts
@hxy91819

hxy91819 commented Apr 2, 2026

Copy link
Copy Markdown
Member

@codex review

@hxy91819 hxy91819 self-assigned this Apr 2, 2026
@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. More of your lovely PRs please.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

singleGanghood and others added 4 commits April 2, 2026 21:58
…I-assisted]

Plugin install fails when a third-party plugin manifest (openclaw.plugin.json)
contains JSON5 features such as trailing commas, comments, or unquoted keys.
The strict JSON.parse used in loadPluginManifest and loadBundleManifestRaw
rejects these files during the config validation step of writeConfigFile,
preventing the install from completing.

- Replace JSON.parse with JSON5.parse in manifest.ts and bundle-manifest.ts
- Add JSON5 tolerance tests covering trailing commas, comments, unquoted keys
- Verified zero regression across manifest-registry, bundle-manifest, install,
  installs, and io.write-config test suites (101 tests pass)

AI-assisted: code fix and test generation verified by automated test runs
@hxy91819 hxy91819 force-pushed the fix/issue-57734-plugin-install-config-json branch from 2c96a0b to 58a4d53 Compare April 2, 2026 14:00
@hxy91819 hxy91819 merged commit ecf7231 into openclaw:main Apr 2, 2026
26 checks passed
@hxy91819

hxy91819 commented Apr 2, 2026

Copy link
Copy Markdown
Member

Merged via squash.

Thanks @singleGanghood!

ngutman pushed a commit that referenced this pull request Apr 3, 2026
…ed] (#59084)

Merged via squash.

Prepared head SHA: 58a4d53
Co-authored-by: singleGanghood <179357632+singleGanghood@users.noreply.github.com>
Co-authored-by: hxy91819 <8814856+hxy91819@users.noreply.github.com>
Reviewed-by: @hxy91819
steipete pushed a commit to duncanita/openclaw that referenced this pull request Apr 4, 2026
…I-assisted] (openclaw#59084)

Merged via squash.

Prepared head SHA: 58a4d53
Co-authored-by: singleGanghood <179357632+singleGanghood@users.noreply.github.com>
Co-authored-by: hxy91819 <8814856+hxy91819@users.noreply.github.com>
Reviewed-by: @hxy91819
lovewanwan pushed a commit to lovewanwan/openclaw that referenced this pull request Apr 28, 2026
…I-assisted] (openclaw#59084)

Merged via squash.

Prepared head SHA: 58a4d53
Co-authored-by: singleGanghood <179357632+singleGanghood@users.noreply.github.com>
Co-authored-by: hxy91819 <8814856+hxy91819@users.noreply.github.com>
Reviewed-by: @hxy91819
ogt-redknie pushed a commit to ogt-redknie/OPENX that referenced this pull request May 2, 2026
…I-assisted] (openclaw#59084)

Merged via squash.

Prepared head SHA: 58a4d53
Co-authored-by: singleGanghood <179357632+singleGanghood@users.noreply.github.com>
Co-authored-by: hxy91819 <8814856+hxy91819@users.noreply.github.com>
Reviewed-by: @hxy91819
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request May 9, 2026
…I-assisted] (openclaw#59084)

Merged via squash.

Prepared head SHA: 58a4d53
Co-authored-by: singleGanghood <179357632+singleGanghood@users.noreply.github.com>
Co-authored-by: hxy91819 <8814856+hxy91819@users.noreply.github.com>
Reviewed-by: @hxy91819
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request May 24, 2026
…I-assisted] (openclaw#59084)

Merged via squash.

Prepared head SHA: 58a4d53
Co-authored-by: singleGanghood <179357632+singleGanghood@users.noreply.github.com>
Co-authored-by: hxy91819 <8814856+hxy91819@users.noreply.github.com>
Reviewed-by: @hxy91819
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Plugin install fails: @vectorize-io/hindsight-openclaw config validation error (JSON syntax error at line 219)

2 participants