Plugin bundling its own marketplace.json corrupts settings.json via an incomplete extraKnownMarketplaces stub
Title: Plugin bundling its own marketplace.json corrupts settings.json via an incomplete extraKnownMarketplaces stub
Environment
- Claude Code: 2.1.211 (VSCode extension, darwin-arm64)
- macOS: 26.5.2 (build 25F84)
- Settings source:
~/.claude/settings.json(user settings)
Summary
When a plugin is installed from an external git repo that itself contains a .claude-plugin/marketplace.json (i.e. the plugin repo doubles as its own marketplace), Claude Code appears to auto-register that embedded marketplace name into extraKnownMarketplaces in settings.json — but writes only {"autoUpdate": true}, without a source field. Since source is required by the settings schema, this makes the entire settings.json file fail validation, and Claude Code discards all settings from it (permissions, enabled plugins, model choice, effortLevel, etc.) with only a generic warning.
Repro
- Enable the
dotnet-pilotplugin from theclaude-communitymarketplace (dotnet-pilot@claude-community). Its declared source inclaude-community'smarketplace.jsonis:
``json``
{
"name": "dotnet-pilot",
"source": {
"source": "url",
"url": "https://github.com/zdanovichnick/dotnet-pilot.git",
"sha": "2b6976f99a243e75d854998dc45260cbbced7232"
}
}
- That repo bundles its own
.claude-plugin/marketplace.json, self-declaring:
``json``
{ "name": "dotnet-pilot-marketplace", "owner": { ... }, "plugins": [...] }
- At some point during plugin install/reconciliation (exact trigger unclear — observed after normal usage/auto-update, not a manual
marketplace add),~/.claude/settings.jsongains:
``json`
"extraKnownMarketplaces": {
...
"dotnet-pilot-marketplace": { "autoUpdate": true }
}
source` key.
with no
- On next startup, Claude Code reports:
> Settings file failed to parse: /Users/<user>/.claude/settings.json — Expected object, but received undefined. Permission rules and other settings from this file are not in effect.
- Note:
~/.claude/plugins/known_marketplaces.json(the file that tracks resolved marketplaces) has no entry fordotnet-pilot-marketplaceat all — the stub only ever appears, incomplete, insettings.json.
Expected behavior
- Either don't auto-register a plugin's self-embedded marketplace manifest into
extraKnownMarketplacesat all (it's not something the user asked to add), or - If it is registered, populate a valid
source(e.g. inherit the sameurl/shathe plugin itself was installed from), so the entry is schema-valid. - Regardless of the above,
settings.jsonschema validation failing on one sub-entry should not discard the entire file's settings (permissions, model, plugins). A partial/graceful degradation (ignore just the invalid entry, warn about it) would prevent this from silently dropping unrelated user configuration like permission rules.
Additional observation
This recurred twice for the same user after manually fixing/removing the bad entry, which points to it being re-written by ongoing plugin reconciliation (e.g. tied to marketplace autoUpdate) rather than a one-time install-time fluke. Also observed: with multiple concurrent Claude Code sessions open (different VSCode windows), each holding its own in-memory settings snapshot, any session persisting settings (e.g. on a /model switch) can flush a stale snapshot back to disk — so even a manual fix in one window can be clobbered by another window's later write. Worth considering whether settings persistence should re-read-merge from disk rather than overwrite wholesale from an in-memory copy.
Workaround
Manually edit ~/.claude/settings.json to give the stub entry a valid source (reusing the plugin's own git URL), and/or disable autoUpdate on the parent marketplace to reduce how often reconciliation runs.