[BUG] Cowork plugin upload: server validation_errors[] swallowed — UI shows only generic "Plugin validation failed."

Resolved 💬 2 comments Opened May 5, 2026 by nicklasjepsen Closed Jun 2, 2026

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report
  • [x] I am using the latest version of Claude Code

What's Wrong?

When a .plugin upload is rejected by the server-side validator, Cowork shows the toast "Plugin validation failed." with no further detail — even though the server returns a structured response body that names the failing file, the specific rule it broke, and the limit it exceeded.

The detail is dropped in c2n / uploadPluginViaRemote (in app.asar.vite/build/index.js). The catch block does:

if (o.message.includes("plugin_validation") || o.message.includes("HTTP 400")) {
  const a = o.message.match(/\): (.+)$/);
  const c = a?.[1] ?? "Plugin validation failed.";
  throw new SN(c, true);
}

That regex captures the top-level error.message from the server (which is just "Plugin validation failed." itself), but the actually useful info is in error.details.validation_errors[]. None of it surfaces in the UI, in logs/main.log, or anywhere else on disk.

Concrete example

Server response when a SKILL.md description is too long:

{
  "type": "error",
  "error": {
    "type": "invalid_request_error",
    "message": "Plugin validation failed.",
    "details": {
      "validation_errors": [
        {
          "error_code": "plugin_upload_skill_md_description_too_long",
          "message": "Skill 'skills/auto-capture': field 'description' in SKILL.md must be at most 1024 characters"
        }
      ],
      "error_visibility": "user_facing",
      "error_code": "plugin_upload_validation_failed"
    }
  }
}

What the user sees: "Plugin validation failed." No file name, no rule, no limit. The user has no path forward without inspecting the network response, which isn't possible from the renderer (the upload happens in the main process via net.fetch, so DevTools Network tab is empty).

I only got to the actual error by replaying the upload from the renderer's DevTools Console using fetch with credentials: "include". That's not a workflow most users will find.

Related undocumented limit

The 1024-char description cap on SKILL.md frontmatter isn't in the public plugin reference (https://code.claude.com/docs/en/plugins-reference). Worth either documenting, or at minimum surfacing the violation message — but the underlying UX bug is generic regardless of which specific validation rule fires.

What Should Happen?

Cowork should surface error.details.validation_errors[] to the user. Even a minimal change like joining the messages would be sufficient:

const details = parsedBody?.error?.details?.validation_errors;
const message = details?.length
  ? details.map(v => v.message).join('\n')
  : (regexMatch?.[1] ?? "Plugin validation failed.");
throw new SN(message, true);

Bonus: log the full server response body in main.log when the upload fails, so users without DevTools fluency have a fallback.

Error Messages/Logs

logs/main.log shows the upload starting but nothing about the failure:

14:15:48 [info] [remoteUploadOps] uploadPluginViaRemote filename=vault-skills.zip bytes=13044 overwrite=false
14:15:49 [info] [remoteMarketplaceClient] uploadAccountPlugin marketplaceId=marketplace_xxx filename=vault-skills.zip bytes=13044 overwrite=false
(no further entries about this upload)

Steps to Reproduce

  1. Build a .plugin with a SKILL.md whose description frontmatter is over 1024 characters (or any other server-validation violation).
  2. Upload via the Cowork plugin install dialog.
  3. Observe the generic "Plugin validation failed." toast.
  4. Verify logs/main.log contains no detail and DevTools Network tab is empty (because the upload runs in the Electron main process).

Claude Model

n/a — UI bug, not model-related.

Is this a regression?

Unsure. Has likely been this way since the account-uploads marketplace shipped.

Claude Code Version

Claude 1.5354.0 (Cowork desktop app)

Platform

Anthropic API

Operating System

Windows 11 (MSIX install)

Additional Information

Related: #56303 (same generic error, different cause), #56246 (same generic error for plugin name prefix).

View original on GitHub ↗

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