Personal plugins tab crashes (React #185) when two account marketplaces share the same name
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report (please file separate reports for different bugs)
- [x] I am using the latest version of Claude Code
What's Wrong?
Note on category: this is a bug in the claude.ai web app, not the Claude Code CLI. The template chooser offers no claude.ai-web option, so the generic Bug Report form is the closest fit. Several CLI-specific fields below are answered "N/A"/"Other" for that reason.
Summary
Settings → Plugins → Browse → Personal unmounts the entire SPA to the top-level bootstrap error boundary. It reproduces deterministically whenever the account holds two marketplace records with an identical name but different id. The tab appears to key or de-duplicate the marketplace list on name rather than id, producing a setState loop that trips React's update-depth guard.
This is unrecoverable from the UI: the only surface that would let you delete the duplicate is the surface that crashes.
Actual behaviour
React error #185, fatal error boundary, the whole app unmounts. Error code shown in the UI: 0SL36UM.
Determinism: 5 reproductions out of 5, including a fresh tab. No variation in the console signature.
Impact
The personal marketplace feature is unusable for any account that reaches this state, and the state cannot be exited from the UI. There is no visible list, so there is no delete affordance to reach.
Environment
- claude.ai on the web, Max plan (personal account)
- Chrome 149.0.7827.200 on Linux x86_64
- Reproduced 5 times out of 5, including in a fresh tab; deterministic, no intermittency
- Error code shown in the UI: 0SL36UM
What Should Happen?
The personal marketplaces list renders.
Two marketplace records that share a name but have distinct ids should both be listed and independently manageable — in particular, deletable — rather than collapsing onto one list key and crashing the app.
Error Messages/Logs
Error code shown in the UI: 0SL36UM
Instrumenting window.fetch and console.error in the page gives the true ordering (two independent runs, identical):
t=62371 account-list-plugins (record B) STARTS
t=62486 React error #185 (+115ms)
t=62512 [BOOTSTRAP] Fatal error boundary triggered
t=62371 -> AbortError: signal is aborted without reason
Steps to Reproduce
- Add a personal marketplace from a GitHub repository.
- Add a second personal marketplace whose name matches the first. Two ways this happens in practice:
- a double-submit of the Add flow creates two records for the same repo (ours were created 88ms apart and never de-duplicated);
- or add two repos from different owners with the same repo name, e.g.
alice/pluginsandbob/plugins— the name is derived from the repo name, so they collide.
- Open Settings → Plugins → Browse → Personal.
Expected: the personal marketplaces list renders.
Actual: React error #185, fatal error boundary, whole app unmounts.
Claude Model
None
Is this a regression?
No, this never worked
Last Working Version
_No response_
Claude Code Version
N/A - claude.ai web app, not the Claude Code CLI
Platform
Other
Operating System
Other Linux
Terminal/Shell
Other
Additional Information
Note on the preflight checklist: the "latest version of Claude Code" box is ticked only because the form requires it. This bug is in the claude.ai web application, not the Claude Code CLI, so the CLI version is not applicable and no CLI version was verified. There is no issue category for claude.ai web bugs; Bug Report is the closest fit.
Not a regression: the two duplicate marketplace records were created 88ms apart during the account's initial setup on 2026-07-21, so the personal plugins tab has never rendered successfully for this account.
Evidence / analysis
The account-list-plugins request never receives a response. The abort lands after the React error, i.e. the teardown kills the in-flight request. A network panel renders this as a 503, which is misleading — re-issuing the identical GET by hand returns 200 twelve times out of twelve, with valid bodies for both records.
The app issues exactly one account-list-plugins call, always for the same one of the two records, and never requests the other. Two rows distinct by id but identical by name, of which only one is ever loaded, is the signature of a name-keyed list: the entries collapse onto one key, the resolved row flips each render, each flip schedules another update, and the depth guard trips.
Ruled out
- Backend rejection.
create-account-marketplacereturns 200,sync_status: "success",auto_sync_on_pushworking,last_synced_shatracking the repo's default branch. - Plan/tier gating. Anthropic's own
knowledge-work-pluginsmarketplace answers the equivalent list-plugins call with 200 in the same session. - A server 503. See above — the request is aborted client-side, never answered.
- MCP transport.
GET /v1/toolbox/shttp/mcp/<id>returning 405 appears directly above the React error in the console and looks causal. It is not: a baseline capture of an ordinary page load with no crash shows the same 405s every time, one per MCP server, each immediately followed by a successful POST to the same URL. Routine legacy-transport probing. - Marketplace sync warnings. A
sync_errorspayload was present initially and has since been cleared; the crash reproduces unchanged withsync_errors: null.
Suggested fixes
- Key the marketplace list by
idrather thanname. - Reject or de-duplicate a create request that would produce a duplicate name for the same account.
- Scope the error boundary so a failure in this modal doesn't unmount the app.
Related
Reported via support as Intercom conversation 215475316387112 (no ticket tracking available through that channel).
HAR captures and full console output available on request: the baseline load, the Add-marketplace flow, and the Browse → Personal crash.
Notes on the CLI-oriented fields in this form
- Claude Model: left as "None" — this is not model-related.
- Claude Code Version: N/A, this is the claude.ai web app rather than the Claude Code CLI.
- Platform / Operating System / Terminal: the options assume the CLI, so "Other" / "Other Linux" / "Other" were selected. The actual environment is Chrome 149.0.7827.200 on Linux x86_64 — see the Environment block above.
- Is this a regression: "No, this never worked" — see the note at the top.
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗