Debugging a Critical Marketplace Schema Validation Failure: How One Invalid Field Blocked All Installations
At 10:16 PM ET on October 16th, 2025, a user reported they couldn’t install the Claude Code Plugins marketplace. The error message was clear but devastating:
✘ Failed to add marketplace: Invalid schema: plugins.1: Unrecognized key(s) in object: 'enhances'
Impact: ZERO users could install the marketplace. Complete installation failure.
This is the story of how we debugged it, fixed it, added legal compliance, resolved CI/CD issues, and deployed security improvements - all in under 3 hours.
The Investigation
Step 1: Reproduce and Locate
The first step was understanding what “plugins.1” meant. I searched the marketplace catalogs:
grep -n "enhances" .claude-plugin/marketplace.json
Found it: Line 59-62 in the web-to-github-issue plugin entry:
"enhances": [
"web_search",
"web_fetch"
]
The problem? Claude Code’s marketplace schema doesn’t support the enhances field. This was a field I had added thinking it would be useful metadata, but the CLI rejected it completely.
Step 2: The Two-Catalog Problem
Our marketplace has TWO catalog files:
.claude-plugin/marketplace.extended.json- Source of truth (website metadata).claude-plugin/marketplace.json- Generated CLI catalog (strict schema)
I had manually edited marketplace.json to remove enhances, but our CI workflow regenerates this file from the extended catalog. The fix needed to be in BOTH places.
Lesson learned: Manual edits to generated files = recipe for CI failures.
Step 3: Fix and Regenerate
# Remove from source catalog
vim .claude-plugin/marketplace.extended.json
# (deleted the enhances field)
# Regenerate CLI catalog
node scripts/sync-marketplace.cjs
Output:
✅ Synced CLI marketplace catalog -> .claude-plugin/marketplace.json
Step 4: Validate JSON
jq empty .claude-plugin/marketplace.json && \
jq empty .claude-plugin/marketplace.extended.json && \
echo "✓ Both JSON files are valid"
✓ Both JSON files are valid
Perfect! But pushing to GitHub triggered another problem…
The CI/CD False Positive
GitHub Actions security scan failed:
❌ ERROR: Private key detected!
plugins/examples/skills-powerkit/skills/plugin-auditor/SKILL.md:- ❌ No private keys (BEGIN PRIVATE KEY)
plugins/examples/skills-powerkit/skills/plugin-validator/SKILL.md:- ❌ No private keys (BEGIN PRIVATE KEY)
Wait, what? These are documentation files explaining what patterns to look for during security audits. They’re not actual private keys!
The Problem
Our security scan excluded README.md files from private key detection, but not SKILL.md files:
# Before
PRIVATE_KEYS=$(grep -r "BEGIN.*PRIVATE KEY" plugins/ 2>/dev/null | \
grep -v "README.md" | grep -v "Pattern:" || true)
The Fix
# After
PRIVATE_KEYS=$(grep -r "BEGIN.*PRIVATE KEY" plugins/ 2>/dev/null | \
grep -v "README.md" | grep -v "SKILL.md" | grep -v "Pattern:" || true)
Lesson learned: Security scans need context. Documentation about security patterns ≠ actual security violations.
The Legal Compliance Addition
While fixing the critical bug, the user reminded me of an outstanding legal requirement: Terms of Service, Privacy Policy, and Acceptable Use Policy pages.
User’s exact words: “this of legal importance update all my websites make sure this is oresent dtafg with claude code plugins”
Implementation: GetTerms.io Integration
Instead of writing legal documents from scratch (dangerous!), we used GetTerms.io - a service that maintains professionally-written, legally-compliant documents.
Three new Astro pages created:
// marketplace/src/pages/terms.astro
<div class="getterms-document-embed"
data-getterms="wH2cn" // Account ID
data-getterms-document="terms-of-service"
data-getterms-lang="en-us"
data-getterms-mode="direct"
data-getterms-env="https://gettermscdn.com">
</div>
Similar structure for /privacy and /acceptable-use.
Styling Dynamic Content
The challenge? GetTerms.io injects HTML dynamically, which Astro’s scoped styles don’t reach.
Solution: Use :global() selectors:
.getterms-document-embed :global(h2) {
color: var(--green-400);
font-size: 1.75rem;
margin-top: 2rem;
}
.getterms-document-embed :global(a) {
color: var(--green-400);
text-decoration: underline;
}
Footer Integration
Added legal links to every page:
<div class="footer-section">
<h4 class="footer-heading">Legal</h4>
<ul class="footer-links">
<li><a href="/terms">Terms of Service</a></li>
<li><a href="/privacy">Privacy Policy</a></li>
<li><a href="/acceptable-use">Acceptable Use</a></li>
</ul>
</div>
Result: 7 total pages deployed (was 4).
The X/Twitter Warning
After deployment, the user reported: “when a user clicks my link in an x oost it says ny site isnt safe go back”
This is a common issue with new domains. X/Twitter flags domains without trust signals as potentially unsafe.
The Problem
claudecodeplugins.io was deployed the same day. New domain + no security headers = X flags it.
The Fix: Security Headers via Meta Tags
GitHub Pages doesn’t let you set HTTP headers, but you can use meta tags:
<!-- Security Headers (via meta tags for GitHub Pages) -->
<meta http-equiv="X-Content-Type-Options" content="nosniff" />
<meta http-equiv="X-Frame-Options" content="SAMEORIGIN" />
<meta http-equiv="Referrer-Policy" content="strict-origin-when-cross-origin" />
<meta http-equiv="Permissions-Policy" content="geolocation=(), microphone=(), camera=()" />
Enhanced Twitter Cards
<!-- Twitter -->
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:site" content="@jeremylongshore" />
<meta name="twitter:creator" content="@jeremylongshore" />
Expected timeline:
- Short term (1-7 days): Some users may still see warnings
- Long term: Domain builds trust, warnings disappear
Deployment Timeline
Here’s how fast we moved once the bug was identified:
10:16 PM ET - User reports installation failure
10:44 PM ET - Fix committed (failed: npm cache issue)
10:45 PM ET - Catalog sync (failed: security scan false positive)
10:46 PM ET - Security scan fix (passed ✅)
10:47 PM ET - Manual marketplace deployment (passed ✅)
Total time from bug report to fix deployed: 31 minutes.
The Release
All changes documented in CHANGELOG.md as v1.0.43:
## [1.0.43] - 2025-10-16
### 🎉 Highlights
**🚨 CRITICAL MARKETPLACE FIX + Legal Compliance**
### 🔧 Critical Bug Fixes
**Marketplace Installation Blocker (HIGH SEVERITY)**
- Error: Invalid schema: plugins.1: Unrecognized key(s) in object: 'enhances'
- Impact: NO users could install marketplace
- Fix: Removed unsupported field from both marketplace catalogs
Git tags created:
git tag -a v1.0.43 -m "Release v1.0.43: Critical marketplace fix + legal compliance"
git push origin v1.0.43
What I Learned
1. Schema Validation is Binary
One invalid field = complete failure. There’s no partial success, no warnings - just “NO.”
Takeaway: Validate against schemas religiously, especially for public APIs.
2. Two-Catalog Systems Need Discipline
Our extended catalog is the source of truth. The CLI catalog is generated. Never manually edit generated files.
Solution: Added CI step that fails if catalogs are out of sync:
- name: Sync CLI marketplace catalog
run: |
node scripts/sync-marketplace.cjs
if ! git diff --quiet .claude-plugin/marketplace.json; then
echo "Marketplace CLI catalog was out of date"
exit 1
fi
3. Security Scans Need Context
A security scan that flags documentation about security patterns is a false positive generator.
Better approach: Use exclusion patterns thoughtfully:
- Exclude documentation files (README.md, SKILL.md)
- Exclude “Pattern:” mentions (indicating examples)
- Still catch actual secrets
4. Legal Compliance is Non-Negotiable
When users say “this of legal importance,” they mean it. GetTerms.io saved hours of legal research and potential liability.
5. New Domains Need Trust Signals
X/Twitter, Google, and other platforms flag new domains aggressively. Security headers help, but time builds trust.
Immediate actions:
- Add security meta tags
- Submit for manual review
- Get organic engagement (each “Continue” click helps)
Final Results
Before This Session:
- ❌ ZERO users could install marketplace
- ❌ Schema validation error on installation
- ❌ No legal pages (Terms, Privacy, Acceptable Use)
- ❌ CI security scan had false positives
- ❌ No security headers for X/Twitter
After This Session:
- ✅ Marketplace installation works for all users
- ✅ Schema validation passes
- ✅ Full legal compliance with embedded policies
- ✅ CI/CD passing without false positives
- ✅ Security headers deployed
- ✅ 7 pages deployed to claudecodeplugins.io
Installation now works:
/plugin marketplace add jeremylongshore/claude-code-plugins
✅ Success! Marketplace added
Try It Yourself
The complete fix is open source:
# View the commits
git log --oneline fb87448..5865a92
# See the marketplace
https://claudecodeplugins.io/
# Install plugins
/plugin marketplace add jeremylongshore/claude-code-plugins
/plugin install skills-powerkit@claude-code-plugins-plus
Related Reading
- Building Production Testing Suite with Playwright and GitHub Actions - More CI/CD automation patterns
- Deploying Next.js 15 to Google Cloud Run with Custom Domains - Production deployment best practices
- Master Directory Standards Prompt for Repository Organization - Keeping codebases organized
The Bottom Line: One invalid schema field broke everything. But systematic debugging, proper CI/CD discipline, and attention to legal/security requirements turned a critical bug into a comprehensive improvement.
Time from bug report to fully deployed fix: 31 minutes.
Lessons for your next debugging session:
- Validate against schemas before pushing
- Never manually edit generated files
- Use exclusion patterns thoughtfully in security scans
- Legal compliance isn’t optional
- New domains need security headers
What’s the worst schema validation bug you’ve encountered? Let me know on X/Twitter!