[BUG] Cowork: account-scoped git marketplace "Check for updates" always fails first attempt with MARKETPLACE_ERROR:NOT_REGISTERED, recovers only via refreshMarketplaceViaRemote
Environment
- Claude Desktop (Cowork / local agent mode), macOS (Darwin 25.5.0)
- Marketplace: an account-scoped GitHub marketplace added from a private repo via the Claude GitHub App
- Reproduced across two Macs, same account.
Summary
Clicking a marketplace's ⋮ → Check for updates surfaces "plugin sync failed" on the first attempt, every time. The underlying error is MARKETPLACE_ERROR:NOT_REGISTERED, thrown by the CustomPlugins.refreshMarketplace IPC call. The update only succeeds after a retry — either an automatic one ~30s later, or a manual "leave the marketplace and reopen it from Customize → Plugins" — which routes through refreshMarketplaceViaRemote → syncAccountMarketplace → pollSyncUntilDone status=success.
Reproducibility
3 of 3 Check-for-updates invocations failed on the first attempt (100%), across two machines. Zero first-try successes.
Steps to reproduce
- Add a private GitHub repo as an account marketplace (via the Claude GitHub App), containing a plugin.
- Push a new plugin version (bumped
versionin.claude-plugin/plugin.json) to the repo's default branch. - In Customize → Plugins, open the marketplace's ⋮ → Check for updates.
Expected
The marketplace re-syncs the repo and the plugin updates to the pushed version.
Actual
The first attempt fails — UI shows "plugin sync failed"; logs show MARKETPLACE_ERROR:NOT_REGISTERED. A retry or a reopen-the-marketplace then succeeds. (The plugin-detail "Update" button also stays greyed on "On latest version" until the marketplace itself re-syncs.)
Log evidence (~/Library/Logs/Claude/main*.log, identifiers redacted)
Two update cycles, both failing first:
# Cycle 1 — 1 failure, then success
[info] [CCDMarketplacePluginManagerCLI] Refreshing marketplace: <my-marketplace>
[error] [REACT_QUERY_CLIENT] ...CustomPlugins_$_refreshMarketplace: Error: MARKETPLACE_ERROR:NOT_REGISTERED
[info] [remoteMarketplaceOps] refreshMarketplaceViaRemote backendId=<redacted>
[info] [remoteMarketplaceClient] syncAccountMarketplace id=<redacted>
[info] [remoteMarketplaceClient] pollSyncUntilDone id=<redacted> settled with status=success after 2559ms
# Cycle 2 — 2 failures, then success
[error] [REACT_QUERY_CLIENT] ...refreshMarketplace: Error: MARKETPLACE_ERROR:NOT_REGISTERED
[error] [REACT_QUERY_CLIENT] ...refreshMarketplace: Error: MARKETPLACE_ERROR:NOT_REGISTERED
[info] [remoteMarketplaceClient] syncAccountMarketplace id=<redacted>
[info] [remoteMarketplaceClient] pollSyncUntilDone id=<redacted> settled with status=success after 2981ms
Root-cause hypothesis
The account-scoped marketplace is not present in the local registry — neither ~/.claude/plugins/known_marketplaces.json nor the Cowork .../cowork_plugins/known_marketplaces.json lists it (it is account-scoped / server-side). The direct refreshMarketplace path appears to resolve the marketplace locally, finds it unregistered, and throws NOT_REGISTERED. The refreshMarketplaceViaRemote path (server-side) works, but is only reached after the first failure.
Impact
Every update requires a retry or a manual reopen. "plugin sync failed" reads as a real failure, so a user reasonably assumes the update is broken and gives up. Not data-affecting — the published release is fine; this is purely the client-side refresh leg.
Suggested fix
Have refreshMarketplace fall through to refreshMarketplaceViaRemote for account-scoped marketplaces (or register them locally at add-time), so the first Check-for-updates succeeds without a retry.
Related issues (this appears distinct from all of them)
- #73673 — Desktop: personal git-marketplace plugins never auto-update; Update button is a silent no-op. Related theme, different code path: #73673 is the CLI/
claude pluginpath where the Update button logs nothing and the marketplace is inknown_marketplaces.json. This report is the Cowork account-scoped path, where Check-for-updates does log (CCDMarketplacePluginManagerCLI Refreshing marketplace), failsNOT_REGISTERED, then recovers viarefreshMarketplaceViaRemote, and the marketplace is not inknown_marketplaces.json(server-side). - #83777 — Plugin "Update now" writes metadata without refreshing marketplace source. Same "update path doesn't refresh source" family.
- #82064 — Plugin install fails with malformed marketplace path after marketplace remove/re-add in same session. Adjacent to the "reopen the marketplace to force a sync" workaround here.
Suggested labels: bug, has repro, area:cowork, area:plugins, area:desktop, platform:macos
3 Comments
Corroborating this on a different configuration, where the fallback never fires — so the failure is permanent rather than first-attempt-only.
Environment
Memolok-marketplace(derived from the repo). The same marketplace CLI-side:memolok(thenamefield in.claude-plugin/marketplace.json)That last point may sharpen your root-cause hypothesis. It isn't only that the account-scoped marketplace is absent from
known_marketplaces.json— the two surfaces also name it differently, so the value passed to the CLI can never match a registry entry.What matches your report
⋮ → Check for updatesfails withMARKETPLACE_ERROR:NOT_REGISTEREDthrown byCustomPlugins_$_refreshMarketplace, and the plugin-detail Update button stays greyed.What differs: the fallback never fires
28 consecutive failures over 25 hours, 2026-08-27 16:34:50 → 2026-08-28 15:13:26 (UTC+3). Across the machine's entire log history:
refreshMarketplaceViaRemote— 0 occurrencessyncAccountMarketplace— 0 occurrencespollSyncUntilDone— 1 occurrence, everThat single occurrence was at install time, nine days earlier:
So on this machine the remote path has only ever run off an install, never off a refresh. Rapid re-clicks (9 seconds apart) don't trigger it, and neither does the ~30s automatic retry you observed.
Separately: that sync carries a marketplace id which differs from the one the current account record reports (
marketplace_01Jn…bAQethen,marketplace_01HL…pqErnow), and the current id appears nowhere inmain.log. I can't tell from the client side whether the registration was recreated or the id is simply only logged on the remote path. Full ids available if that helps.The read path is healthy; only refresh is dead
fetchAccountScopedRemotePlugins: 1 plugins from 1 marketplace(s)runs hourly and succeeds throughout. The account record stays readable and pinned —updatedAtfrozen at2026-08-27T11:53:46ZwithupdatedAtVerified: true— while the source repo'smainhas carried a newer plugin version since2026-08-27T13:24:32Z.Ruled out
claude plugin validatepasses,--strictincluded; the release diff is prose plus a version bump, and the CLI installs that same commit without complaint.⋮menu offers only Edit with Claude and Remove — no update control at all. The Desktop control is the only one that exists.A data point for your suggested fix
Your suggestion offers two options: fall through to
refreshMarketplaceViaRemote, or register account-scoped marketplaces locally at add-time. The second one does not work.Registering a CLI-side marketplace under the matching name makes the button report success — while refreshing that local marketplace and leaving the account record untouched. Resolving the name locally removes the error without moving the thing the user is trying to update, converting a visible failure into a silent one. The fall-through looks like the only safe half of that suggestion.
Impact
This is a pre-launch plugin distributed to invited testers, whose MCP server enforces a minimum plugin version. A tester below that floor is refused by the server, told to update, and has no working route to do so: the Desktop control errors, the web surface has no control, and reinstalling returns the stale version.
As the publisher I can't fix it from my side either — nothing pushed to the source repo can move an account record that never re-resolves.
Reproduced on macOS, with the same permanent failure as the Windows report above.
Environment: Claude Desktop 2.19675.0, macOS 27.2, Claude Code 2.1.282. Marketplace
skillsadded at account scope from GitHubmattpocock/skills, pluginmattpocock-skills1.2.3.Symptom: the plugin's ⋮ menu → "Check for updates" always shows "Couldn't check for updates. Try again."
main.log:Repeated at every attempt, with no fallback to a remote refresh.
Name mismatch again: the account-side marketplace is
skills. The repo's.claude-plugin/marketplace.jsonnames itmattpocock.claude plugin marketplace listshows neither, so the refresh can never resolve.Also tried:
claude-plugins-official, which made no difference.This supports the earlier point that registering the marketplace locally wouldn't fix it. The fall-through to the remote refresh looks like the right fix.
Still reproducible on current versions, as of 2026-10-12:
<Repo-Name>(derived from the repo), and thenamein.claude-plugin/marketplace.jsonis<repo-name>(lowercase). This is the same name mismatch noted in the Windows report above.Like the Windows and macOS reports above, the failure is permanent:
refreshMarketplaceViaRemotenever fires.The plugins still reach the Code tab through the background account sync: the synced copies were on the latest versions. So the error is misleading rather than blocking.
In our case most users have no GitHub access. They get the plugins only through the Claude.ai org marketplace, so registering the marketplace locally in the CLI isn't a workaround for them. The refresh needs to go through the remote path.