Plugin 'Update now' / writes metadata without refreshing marketplace source (gh-76882 + gh-83422 combined root cause)

Status Fixed / completed
Reported on v2.1.212
Maintainer reply None cached
Activity 2 comments · opened Aug 4, 2026 · closed Aug 25, 2026

Bug

claude plugin update / interactive "Update now" calls updatePluginOp (src/services/plugins/pluginOperations.ts) which resolves the plugin entry via getPluginByIdgetPluginByIdCacheOnly — a cache-only fast path that reads the local marketplace clone without touching the network. There is no refreshMarketplace step before version calculation, so the update computes the new version from stale marketplace data.

Reproduction

  1. Install a plugin from a third-party github marketplace (e.g. code-wiki@code-wiki, source { "source": "github", "repo": "ye-c/code-wiki" })
  2. Push a new version (bump plugin.json version) to the remote
  3. Run claude plugin update code-wiki@code-wiki (or click "Update now" in /plugin UI)
  4. Restart Claude Code

Expected: Plugin updated to the new version, /code-wiki skill available.
Actual: installed_plugins.json shows the new version/installPath/lastUpdated/gitCommitSha, but the cache directory at ~/.claude/plugins/cache/{marketplace}/{plugin}/{version}/ is missing or carries stale content. The plugin's skills/commands are silently absent — invoking /code-wiki gets "unknown skill".

Root cause

updatePluginOp (src/services/plugins/pluginOperations.ts) resolves the plugin entry via getPluginById (src/utils/plugins/marketplaceManager.ts), which first tries getPluginByIdCacheOnly — reading only the local marketplace clone. No refreshMarketplace is called beforehand, so:

  • For local-source plugins: the entire update uses the stale marketplace clone's entry.source / entry.version.
  • For remote (github) plugins: cachePlugin re-clones independently (so the SHA is fresh), but entry.version from the stale marketplace clone can still mis-version the cache path.

This is the combined root cause of #76882 (marketplace update fetches new version but doesn't update installed_plugins.json) and #83422 (autoUpdate refreshes marketplace clone but never updates existing installs). The interactive "Update now" button hits the same path via handleSingleOperation('update') in src/commands/plugin/ManagePlugins.tsx.

Workaround

Uninstall + reinstall (bypasses the update path entirely, rebuilds cache + metadata):

claude plugin uninstall <plugin>@<marketplace>
claude plugin install <plugin>@<marketplace>

Fix

Refresh the marketplace source at the top of updatePluginOp before getPluginById, so version calculation uses current data:

// src/services/plugins/pluginOperations.ts, in updatePluginOp
if (marketplaceName) {
  try {
    await refreshMarketplace(marketplaceName)
  } catch (error) {
    logForDebugging(`updatePluginOp: marketplace refresh failed for ${marketplaceName}: ${errorMessage(error)}`)
  }
}

refreshMarketplace already short-circuits for settings-sourced and seed-managed marketplaces (src/utils/plugins/marketplaceManager.ts), so the added call is a no-op for those. Failure is non-fatal — a transient refresh error shouldn't block updating from whatever source is available.

Environment

  • Claude Code 2.1.212, macOS (darwin 25.6.0)
  • Third-party github marketplace, user scope
from cc @ claude-bro

View original on GitHub ↗

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