claude-code - 💡(How to fix) Fix [BUG] Plugin runtime loader and `claude plugin validate` accept divergent schemas

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…

Error Message

I hit this twice in a row on the same plugin during initial publishing — each time, the CLI returned ✔ Validation passed and gh release create succeeded, but installing the published plugin in a clean Claude Code session failed with a Zod schema error from the runtime.

Error Messages/Logs

  1. Runtime error: Validation errors: userConfig.framework: Unrecognized key: "enum". Related (closed, auto-locked, same error message): #31763.

Code Example

Failed to install: Plugin temp_local_1779351806694_0gsi8e has an invalid manifest file at
/Users/<user>/.claude/plugins/cache/.../.claude-plugin/plugin.json.

Validation errors: userConfig.default_framework: Unrecognized key: "enum",
userConfig.default_ui_framework: Unrecognized key: "enum",
userConfig.package_manager: Unrecognized key: "enum"

---

Hook load failed: [
  {
    "expected": "record",
    "code": "invalid_type",
    "path": ["hooks"],
    "message": "Invalid input: expected record, received undefined"
  }
]

---

{
     "name": "demo-plugin",
     "version": "0.1.0",
     "description": "Demo",
     "userConfig": {
       "framework": {
         "type": "string",
         "title": "Framework",
         "description": "Pick one",
         "enum": ["a", "b", "c"],
         "default": "a"
       }
     }
   }

---

{
     "PostToolUse": [
       {
         "matcher": "Write|Edit",
         "hooks": [
           { "type": "command", "command": "echo hi", "timeout": 5 }
         ]
       }
     ]
   }
RAW_BUFFERClick to expand / collapse

What's Wrong?

claude plugin validate and the runtime plugin loader use different schemas. The CLI accepts plugin manifests that the runtime rejects with Zod errors at install/load time. This makes the CLI validator unreliable as a pre-publish check.

I hit this twice in a row on the same plugin during initial publishing — each time, the CLI returned ✔ Validation passed and gh release create succeeded, but installing the published plugin in a clean Claude Code session failed with a Zod schema error from the runtime.

Both bugs match the same closed (auto-locked) issue: #31763.

What Should Happen?

claude plugin validate should use the same schema the runtime uses (or stricter). A manifest accepted by validate should always install successfully.

Error Messages/Logs

Case 1 — userConfig.<field>.enum (runtime, Claude Code 2.1.130+):

Failed to install: Plugin temp_local_1779351806694_0gsi8e has an invalid manifest file at
/Users/<user>/.claude/plugins/cache/.../.claude-plugin/plugin.json.

Validation errors: userConfig.default_framework: Unrecognized key: "enum",
userConfig.default_ui_framework: Unrecognized key: "enum",
userConfig.package_manager: Unrecognized key: "enum"

Case 2 — hooks/hooks.json without outer hooks wrapper (runtime, Claude Code 2.1.150):

Hook load failed: [
  {
    "expected": "record",
    "code": "invalid_type",
    "path": ["hooks"],
    "message": "Invalid input: expected record, received undefined"
  }
]

In both cases, claude plugin validate . returned ✔ Validation passed immediately before publishing.

Steps to Reproduce

Case 1 — userConfig.enum

  1. In a plugin directory, create .claude-plugin/plugin.json with a userConfig field that uses an enum array (a pattern that older plugin docs / JSON-Schema convention would suggest):

    {
      "name": "demo-plugin",
      "version": "0.1.0",
      "description": "Demo",
      "userConfig": {
        "framework": {
          "type": "string",
          "title": "Framework",
          "description": "Pick one",
          "enum": ["a", "b", "c"],
          "default": "a"
        }
      }
    }
  2. Add a minimal .claude-plugin/marketplace.json and run claude plugin validate .✔ Validation passed.

  3. Publish, then try /plugin install demo-plugin@your-marketplace in a clean Claude Code session.

  4. Runtime error: Validation errors: userConfig.framework: Unrecognized key: "enum".

Case 2 — missing hooks wrapper in hooks/hooks.json

  1. In a plugin directory, create hooks/hooks.json with event arrays at the top level (matching the format that ~/.claude/settings.json accepts — which is what some older plugin docs suggested):

    {
      "PostToolUse": [
        {
          "matcher": "Write|Edit",
          "hooks": [
            { "type": "command", "command": "echo hi", "timeout": 5 }
          ]
        }
      ]
    }
  2. Run claude plugin validate .✔ Validation passed.

  3. Install the plugin, then run /doctor.

  4. Doctor reports: Hook load failed: expected record at path "hooks", received undefined.

The runtime requires { "hooks": { "PostToolUse": [...] } }, but claude plugin validate accepts the unwrapped form.

Suggested Fix

Make claude plugin validate reuse the same Zod schemas the runtime loader uses (or have both consume the same source-of-truth). The Zod errors the runtime produces are already excellent — they'd be just as useful at CLI time, before publishing.

Until then, plugin authors have to do a fresh install on every release to confirm the runtime accepts what the validator did, and validate is effectively just a syntax check.

Related (closed, auto-locked, same error message): #31763.

Claude Model

Not relevant — this is a CLI / plugin-loader bug, not a model behavior issue.

Regression

Don't know — I'm a first-time plugin author. Both schemas may have been like this from the start.

Version

Hit on Claude Code 2.1.130 (Case 1, initial install attempts) and 2.1.150 (Case 2, doctor output). Both reproductions still happen on 2.1.150.

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