[BUG] Cowork local plugin upload silently rejects valid plugin.json when description field contains a URL

Resolved 💬 3 comments Opened May 6, 2026 by maximuspwr Closed May 9, 2026

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report (please file separate reports for different bugs)
  • [x] I am using the latest version of Claude Code

What's Wrong?

Surface: Claude Desktop → Cowork tab → Customize → Personal plugins → Upload plugin (Windows 11)
Cowork's local plugin upload (Customize → Personal plugins → Upload plugin) rejects a plugin with the generic error "plugin validation failed" when the description field in .claude-plugin/plugin.json contains a URL. The validation error gives no indication of which field caused the failure or what rule was violated.

URLs are accepted in the typed/structured fields author.url and credits.based_on_url. Only the free-text description field rejects them, and this rule is not documented in the plugin reference.

This was isolated via a single-variable controlled test: two zips identical in every byte except for one URL substring appended to the description field. The version without the URL installs successfully; the version with the URL fails validation. No file, structure, schema, or other content changes between them.

What Should Happen?

Either:

Description should accept URLs - it is documented as a free-text field with no character restrictions, and URLs are common in plugin descriptions for attribution, source links, or supporting documentation references. The validator should not silently reject otherwise-valid JSON strings based on undocumented content rules.
OR if URL rejection in description is intentional (e.g. anti-spam): the validator should return a specific error message naming the field and rule (e.g. "description must not contain URLs; use 'homepage', 'author.url', or 'credits.based_on_url' instead"), and the rule should be documented in the plugin reference at https://code.claude.com/docs/en/plugins-reference.

The current behaviour - silent rejection with a generic "plugin validation failed" message and no field-level diagnostic -makes this bug essentially undebuggable without external bisection.

Error Messages/Logs

"Plugin validation failed"

That is the entire error surfaced in the UI. No field name, no rule name, no line number, no link to docs. No additional information is shown via expandable details, hover tooltips, or anywhere else in the Customize → Personal plugins interface.

Steps to Reproduce

Steps to Reproduce
Minimal reproducer: two near-identical plugin zips, differing only in whether the description contains a URL.
Plugin A (installs successfully) — plugin-a.zip
Folder structure:
test-plugin/
├── .claude-plugin/
│ └── plugin.json
└── skills/
└── test-skill/
└── SKILL.md
.claude-plugin/plugin.json:

{
  "name": "test-plugin",
  "version": "1.0.0",
  "description": "A minimal test plugin for reproducing a validation issue. The description here is free text without any URLs.",
  "author": {
    "name": "test-author"
  },
  "components": {
    "skills": ["skills/test-skill"]
  }
}

skills/test-skill/SKILL.md:

---
name: test-skill
description: A minimal test skill that does nothing. Use this skill only for plugin upload testing.
---
This skill exists to give the test plugin a valid component.

Plugin B (fails validation) - plugin-b.zip
Identical to Plugin A except for one substring added to the description in .claude-plugin/plugin.json:

{
  "name": "test-plugin",
  "version": "1.0.0",
  "description": "A minimal test plugin for reproducing a validation issue. The description here is free text without any URLs. See https://example.com for more info.",
  "author": {
    "name": "test-author"
  },
  "components": {
    "skills": ["skills/test-skill"]
  }
}

The only difference between the two plugin.json files is the trailing sentence "See https://example.com for more info." added to the description. All other fields, all other files, and the folder structure are identical.

Reproduction steps

  1. Create two folders matching the structures above
  2. Zip each folder: zip -r plugin-a.zip test-plugin/ (then modify the description and zip -r plugin-b.zip test-plugin/ for the failing version)
  3. Open Claude Desktop → Cowork tab
  4. Click Customize → Personal plugins → Upload plugin
  5. Select plugin-a.zip → confirm install → succeeds
  6. Remove the test-plugin from Personal plugins (or skip; the install just gets overwritten)
  7. Repeat steps 4-5 with plugin-b.zip → fails with "plugin validation failed"

Confirming the URL is the only variable
Compare the two plugin.json files with diff — exactly one line differs, in the description field, by exactly one URL-containing substring.

Claude Model

Other

Is this a regression?

I don't know

Last Working Version

_No response_

Claude Code Version

1.55354.0 (9a9e3d)

Platform

Anthropic API

Operating System

Windows

Terminal/Shell

Other

Additional Information

_No response_

View original on GitHub ↗

This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗